1/*@internal*/ 2namespace ts { 3 export function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, 4 cancellationToken?: CancellationToken, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitOutput { 5 const outputFiles: OutputFile[] = []; 6 const { emitSkipped, diagnostics, exportedModulesFromDeclarationEmit } = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, forceDtsEmit); 7 return { outputFiles, emitSkipped, diagnostics, exportedModulesFromDeclarationEmit }; 8 9 function writeFile(fileName: string, text: string, writeByteOrderMark: boolean) { 10 outputFiles.push({ name: fileName, writeByteOrderMark, text }); 11 } 12 } 13 14 export interface ReusableBuilderState { 15 /** 16 * Information of the file eg. its version, signature etc 17 */ 18 fileInfos: ReadonlyESMap<Path, BuilderState.FileInfo>; 19 /** 20 * Contains the map of ReferencedSet=Referenced files of the file if module emit is enabled 21 * Otherwise undefined 22 * Thus non undefined value indicates, module emit 23 */ 24 readonly referencedMap?: ReadonlyESMap<Path, BuilderState.ReferencedSet> | undefined; 25 /** 26 * Contains the map of exported modules ReferencedSet=exported module files from the file if module emit is enabled 27 * Otherwise undefined 28 */ 29 readonly exportedModulesMap?: ReadonlyESMap<Path, BuilderState.ReferencedSet> | undefined; 30 } 31 32 export interface BuilderState { 33 /** 34 * Information of the file eg. its version, signature etc 35 */ 36 fileInfos: ESMap<Path, BuilderState.FileInfo>; 37 /** 38 * Contains the map of ReferencedSet=Referenced files of the file if module emit is enabled 39 * Otherwise undefined 40 * Thus non undefined value indicates, module emit 41 */ 42 readonly referencedMap: ReadonlyESMap<Path, BuilderState.ReferencedSet> | undefined; 43 /** 44 * Contains the map of exported modules ReferencedSet=exported module files from the file if module emit is enabled 45 * Otherwise undefined 46 */ 47 readonly exportedModulesMap: ESMap<Path, BuilderState.ReferencedSet> | undefined; 48 /** 49 * Map of files that have already called update signature. 50 * That means hence forth these files are assumed to have 51 * no change in their signature for this version of the program 52 */ 53 hasCalledUpdateShapeSignature: Set<Path>; 54 /** 55 * Cache of all files excluding default library file for the current program 56 */ 57 allFilesExcludingDefaultLibraryFile?: readonly SourceFile[]; 58 /** 59 * Cache of all the file names 60 */ 61 allFileNames?: readonly string[]; 62 } 63 64 export namespace BuilderState { 65 /** 66 * Information about the source file: Its version and optional signature from last emit 67 */ 68 export interface FileInfo { 69 readonly version: string; 70 signature: string | undefined; 71 affectsGlobalScope: boolean; 72 } 73 /** 74 * Referenced files with values for the keys as referenced file's path to be true 75 */ 76 export type ReferencedSet = ReadonlySet<Path>; 77 /** 78 * Compute the hash to store the shape of the file 79 */ 80 export type ComputeHash = ((data: string) => string) | undefined; 81 82 /** 83 * Exported modules to from declaration emit being computed. 84 * This can contain false in the affected file path to specify that there are no exported module(types from other modules) for this file 85 */ 86 export type ComputingExportedModulesMap = ESMap<Path, ReferencedSet | false>; 87 88 /** 89 * Get the referencedFile from the imported module symbol 90 */ 91 function getReferencedFileFromImportedModuleSymbol(symbol: Symbol) { 92 if (symbol.declarations && symbol.declarations[0]) { 93 const declarationSourceFile = getSourceFileOfNode(symbol.declarations[0]); 94 return declarationSourceFile && declarationSourceFile.resolvedPath; 95 } 96 } 97 98 /** 99 * Get the referencedFile from the import name node from file 100 */ 101 function getReferencedFileFromImportLiteral(checker: TypeChecker, importName: StringLiteralLike) { 102 const symbol = checker.getSymbolAtLocation(importName); 103 return symbol && getReferencedFileFromImportedModuleSymbol(symbol); 104 } 105 106 /** 107 * Gets the path to reference file from file name, it could be resolvedPath if present otherwise path 108 */ 109 function getReferencedFileFromFileName(program: Program, fileName: string, sourceFileDirectory: Path, getCanonicalFileName: GetCanonicalFileName): Path { 110 return toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName); 111 } 112 113 /** 114 * Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true 115 */ 116 function getReferencedFiles(program: Program, sourceFile: SourceFile, getCanonicalFileName: GetCanonicalFileName): Set<Path> | undefined { 117 let referencedFiles: Set<Path> | undefined; 118 119 // We need to use a set here since the code can contain the same import twice, 120 // but that will only be one dependency. 121 // To avoid invernal conversion, the key of the referencedFiles map must be of type Path 122 if (sourceFile.imports && sourceFile.imports.length > 0) { 123 const checker: TypeChecker = program.getTypeChecker(); 124 for (const importName of sourceFile.imports) { 125 const declarationSourceFilePath = getReferencedFileFromImportLiteral(checker, importName); 126 if (declarationSourceFilePath) { 127 addReferencedFile(declarationSourceFilePath); 128 } 129 } 130 } 131 132 const sourceFileDirectory = getDirectoryPath(sourceFile.resolvedPath); 133 // Handle triple slash references 134 if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) { 135 for (const referencedFile of sourceFile.referencedFiles) { 136 const referencedPath = getReferencedFileFromFileName(program, referencedFile.fileName, sourceFileDirectory, getCanonicalFileName); 137 addReferencedFile(referencedPath); 138 } 139 } 140 141 // Handle type reference directives 142 if (sourceFile.resolvedTypeReferenceDirectiveNames) { 143 sourceFile.resolvedTypeReferenceDirectiveNames.forEach((resolvedTypeReferenceDirective) => { 144 if (!resolvedTypeReferenceDirective) { 145 return; 146 } 147 148 const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217 149 const typeFilePath = getReferencedFileFromFileName(program, fileName, sourceFileDirectory, getCanonicalFileName); 150 addReferencedFile(typeFilePath); 151 }); 152 } 153 154 // Add module augmentation as references 155 if (sourceFile.moduleAugmentations.length) { 156 const checker = program.getTypeChecker(); 157 for (const moduleName of sourceFile.moduleAugmentations) { 158 if (!isStringLiteral(moduleName)) { continue; } 159 const symbol = checker.getSymbolAtLocation(moduleName); 160 if (!symbol) { continue; } 161 162 // Add any file other than our own as reference 163 addReferenceFromAmbientModule(symbol); 164 } 165 } 166 167 // From ambient modules 168 for (const ambientModule of program.getTypeChecker().getAmbientModules()) { 169 if (ambientModule.declarations.length > 1) { 170 addReferenceFromAmbientModule(ambientModule); 171 } 172 } 173 174 return referencedFiles; 175 176 function addReferenceFromAmbientModule(symbol: Symbol) { 177 // Add any file other than our own as reference 178 for (const declaration of symbol.declarations) { 179 const declarationSourceFile = getSourceFileOfNode(declaration); 180 if (declarationSourceFile && 181 declarationSourceFile !== sourceFile) { 182 addReferencedFile(declarationSourceFile.resolvedPath); 183 } 184 } 185 } 186 187 function addReferencedFile(referencedPath: Path) { 188 (referencedFiles || (referencedFiles = new Set())).add(referencedPath); 189 } 190 } 191 192 /** 193 * Returns true if oldState is reusable, that is the emitKind = module/non module has not changed 194 */ 195 export function canReuseOldState(newReferencedMap: ReadonlyESMap<Path, ReferencedSet> | undefined, oldState: Readonly<ReusableBuilderState> | undefined) { 196 return oldState && !oldState.referencedMap === !newReferencedMap; 197 } 198 199 /** 200 * Creates the state of file references and signature for the new program from oldState if it is safe 201 */ 202 export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<ReusableBuilderState>): BuilderState { 203 const fileInfos = new Map<Path, FileInfo>(); 204 const referencedMap = newProgram.getCompilerOptions().module !== ModuleKind.None ? new Map<Path, ReferencedSet>() : undefined; 205 const exportedModulesMap = referencedMap ? new Map<Path, ReferencedSet>() : undefined; 206 const hasCalledUpdateShapeSignature = new Set<Path>(); 207 const useOldState = canReuseOldState(referencedMap, oldState); 208 209 // Ensure source files have parent pointers set 210 newProgram.getTypeChecker(); 211 212 // Create the reference map, and set the file infos 213 for (const sourceFile of newProgram.getSourceFiles()) { 214 const version = Debug.checkDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set"); 215 const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.resolvedPath) : undefined; 216 if (referencedMap) { 217 const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName); 218 if (newReferences) { 219 referencedMap.set(sourceFile.resolvedPath, newReferences); 220 } 221 // Copy old visible to outside files map 222 if (useOldState) { 223 const exportedModules = oldState!.exportedModulesMap!.get(sourceFile.resolvedPath); 224 if (exportedModules) { 225 exportedModulesMap!.set(sourceFile.resolvedPath, exportedModules); 226 } 227 } 228 } 229 fileInfos.set(sourceFile.resolvedPath, { version, signature: oldInfo && oldInfo.signature, affectsGlobalScope: isFileAffectingGlobalScope(sourceFile) }); 230 } 231 232 return { 233 fileInfos, 234 referencedMap, 235 exportedModulesMap, 236 hasCalledUpdateShapeSignature 237 }; 238 } 239 240 /** 241 * Releases needed properties 242 */ 243 export function releaseCache(state: BuilderState) { 244 state.allFilesExcludingDefaultLibraryFile = undefined; 245 state.allFileNames = undefined; 246 } 247 248 /** 249 * Creates a clone of the state 250 */ 251 export function clone(state: Readonly<BuilderState>): BuilderState { 252 // Dont need to backup allFiles info since its cache anyway 253 return { 254 fileInfos: new Map(state.fileInfos), 255 referencedMap: state.referencedMap && new Map(state.referencedMap), 256 exportedModulesMap: state.exportedModulesMap && new Map(state.exportedModulesMap), 257 hasCalledUpdateShapeSignature: new Set(state.hasCalledUpdateShapeSignature), 258 }; 259 } 260 261 /** 262 * Gets the files affected by the path from the program 263 */ 264 export function getFilesAffectedBy(state: BuilderState, programOfThisState: Program, path: Path, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, cacheToUpdateSignature?: ESMap<Path, string>, exportedModulesMapCache?: ComputingExportedModulesMap): readonly SourceFile[] { 265 // Since the operation could be cancelled, the signatures are always stored in the cache 266 // They will be committed once it is safe to use them 267 // eg when calling this api from tsserver, if there is no cancellation of the operation 268 // In the other cases the affected files signatures are committed only after the iteration through the result is complete 269 const signatureCache = cacheToUpdateSignature || new Map(); 270 const sourceFile = programOfThisState.getSourceFileByPath(path); 271 if (!sourceFile) { 272 return emptyArray; 273 } 274 275 if (!updateShapeSignature(state, programOfThisState, sourceFile, signatureCache, cancellationToken, computeHash, exportedModulesMapCache)) { 276 return [sourceFile]; 277 } 278 279 const result = (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, signatureCache, cancellationToken, computeHash, exportedModulesMapCache); 280 if (!cacheToUpdateSignature) { 281 // Commit all the signatures in the signature cache 282 updateSignaturesFromCache(state, signatureCache); 283 } 284 return result; 285 } 286 287 /** 288 * Updates the signatures from the cache into state's fileinfo signatures 289 * This should be called whenever it is safe to commit the state of the builder 290 */ 291 export function updateSignaturesFromCache(state: BuilderState, signatureCache: ESMap<Path, string>) { 292 signatureCache.forEach((signature, path) => updateSignatureOfFile(state, signature, path)); 293 } 294 295 export function updateSignatureOfFile(state: BuilderState, signature: string | undefined, path: Path) { 296 state.fileInfos.get(path)!.signature = signature; 297 state.hasCalledUpdateShapeSignature.add(path); 298 } 299 300 /** 301 * Returns if the shape of the signature has changed since last emit 302 */ 303 export function updateShapeSignature(state: Readonly<BuilderState>, programOfThisState: Program, sourceFile: SourceFile, cacheToUpdateSignature: ESMap<Path, string>, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache?: ComputingExportedModulesMap) { 304 Debug.assert(!!sourceFile); 305 Debug.assert(!exportedModulesMapCache || !!state.exportedModulesMap, "Compute visible to outside map only if visibleToOutsideReferencedMap present in the state"); 306 307 // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate 308 if (state.hasCalledUpdateShapeSignature.has(sourceFile.resolvedPath) || cacheToUpdateSignature.has(sourceFile.resolvedPath)) { 309 return false; 310 } 311 312 const info = state.fileInfos.get(sourceFile.resolvedPath); 313 if (!info) return Debug.fail(); 314 315 const prevSignature = info.signature; 316 let latestSignature: string; 317 if (sourceFile.isDeclarationFile) { 318 latestSignature = sourceFile.version; 319 if (exportedModulesMapCache && latestSignature !== prevSignature) { 320 // All the references in this file are exported 321 const references = state.referencedMap ? state.referencedMap.get(sourceFile.resolvedPath) : undefined; 322 exportedModulesMapCache.set(sourceFile.resolvedPath, references || false); 323 } 324 } 325 else { 326 const emitOutput = getFileEmitOutput( 327 programOfThisState, 328 sourceFile, 329 /*emitOnlyDtsFiles*/ true, 330 cancellationToken, 331 /*customTransformers*/ undefined, 332 /*forceDtsEmit*/ true 333 ); 334 const firstDts = emitOutput.outputFiles && 335 programOfThisState.getCompilerOptions().declarationMap ? 336 emitOutput.outputFiles.length > 1 ? emitOutput.outputFiles[1] : undefined : 337 emitOutput.outputFiles.length > 0 ? emitOutput.outputFiles[0] : undefined; 338 if (firstDts) { 339 Debug.assert(isDeclarationFileName(firstDts.name), "File extension for signature expected to be dts or dets", () => `Found: ${getAnyExtensionFromPath(firstDts.name)} for ${firstDts.name}:: All output files: ${JSON.stringify(emitOutput.outputFiles.map(f => f.name))}`); 340 latestSignature = (computeHash || generateDjb2Hash)(firstDts.text); 341 if (exportedModulesMapCache && latestSignature !== prevSignature) { 342 updateExportedModules(sourceFile, emitOutput.exportedModulesFromDeclarationEmit, exportedModulesMapCache); 343 } 344 } 345 else { 346 latestSignature = prevSignature!; // TODO: GH#18217 347 } 348 349 } 350 cacheToUpdateSignature.set(sourceFile.resolvedPath, latestSignature); 351 352 return !prevSignature || latestSignature !== prevSignature; 353 } 354 355 /** 356 * Coverts the declaration emit result into exported modules map 357 */ 358 function updateExportedModules(sourceFile: SourceFile, exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined, exportedModulesMapCache: ComputingExportedModulesMap) { 359 if (!exportedModulesFromDeclarationEmit) { 360 exportedModulesMapCache.set(sourceFile.resolvedPath, false); 361 return; 362 } 363 364 let exportedModules: Set<Path> | undefined; 365 exportedModulesFromDeclarationEmit.forEach(symbol => addExportedModule(getReferencedFileFromImportedModuleSymbol(symbol))); 366 exportedModulesMapCache.set(sourceFile.resolvedPath, exportedModules || false); 367 368 function addExportedModule(exportedModulePath: Path | undefined) { 369 if (exportedModulePath) { 370 if (!exportedModules) { 371 exportedModules = new Set(); 372 } 373 exportedModules.add(exportedModulePath); 374 } 375 } 376 } 377 378 /** 379 * Updates the exported modules from cache into state's exported modules map 380 * This should be called whenever it is safe to commit the state of the builder 381 */ 382 export function updateExportedFilesMapFromCache(state: BuilderState, exportedModulesMapCache: ComputingExportedModulesMap | undefined) { 383 if (exportedModulesMapCache) { 384 Debug.assert(!!state.exportedModulesMap); 385 exportedModulesMapCache.forEach((exportedModules, path) => { 386 if (exportedModules) { 387 state.exportedModulesMap!.set(path, exportedModules); 388 } 389 else { 390 state.exportedModulesMap!.delete(path); 391 } 392 }); 393 } 394 } 395 396 /** 397 * Get all the dependencies of the sourceFile 398 */ 399 export function getAllDependencies(state: BuilderState, programOfThisState: Program, sourceFile: SourceFile): readonly string[] { 400 const compilerOptions = programOfThisState.getCompilerOptions(); 401 // With --out or --outFile all outputs go into single file, all files depend on each other 402 if (outFile(compilerOptions)) { 403 return getAllFileNames(state, programOfThisState); 404 } 405 406 // If this is non module emit, or its a global file, it depends on all the source files 407 if (!state.referencedMap || isFileAffectingGlobalScope(sourceFile)) { 408 return getAllFileNames(state, programOfThisState); 409 } 410 411 // Get the references, traversing deep from the referenceMap 412 const seenMap = new Set<Path>(); 413 const queue = [sourceFile.resolvedPath]; 414 while (queue.length) { 415 const path = queue.pop()!; 416 if (!seenMap.has(path)) { 417 seenMap.add(path); 418 const references = state.referencedMap.get(path); 419 if (references) { 420 const iterator = references.keys(); 421 for (let iterResult = iterator.next(); !iterResult.done; iterResult = iterator.next()) { 422 queue.push(iterResult.value); 423 } 424 } 425 } 426 } 427 428 return arrayFrom(mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); 429 } 430 431 /** 432 * Gets the names of all files from the program 433 */ 434 function getAllFileNames(state: BuilderState, programOfThisState: Program): readonly string[] { 435 if (!state.allFileNames) { 436 const sourceFiles = programOfThisState.getSourceFiles(); 437 state.allFileNames = sourceFiles === emptyArray ? emptyArray : sourceFiles.map(file => file.fileName); 438 } 439 return state.allFileNames; 440 } 441 442 /** 443 * Gets the files referenced by the the file path 444 */ 445 export function getReferencedByPaths(state: Readonly<BuilderState>, referencedFilePath: Path) { 446 return arrayFrom(mapDefinedIterator(state.referencedMap!.entries(), ([filePath, referencesInFile]) => 447 referencesInFile.has(referencedFilePath) ? filePath : undefined 448 )); 449 } 450 451 /** 452 * For script files that contains only ambient external modules, although they are not actually external module files, 453 * they can only be consumed via importing elements from them. Regular script files cannot consume them. Therefore, 454 * there are no point to rebuild all script files if these special files have changed. However, if any statement 455 * in the file is not ambient external module, we treat it as a regular script file. 456 */ 457 function containsOnlyAmbientModules(sourceFile: SourceFile) { 458 for (const statement of sourceFile.statements) { 459 if (!isModuleWithStringLiteralName(statement)) { 460 return false; 461 } 462 } 463 return true; 464 } 465 466 /** 467 * Return true if file contains anything that augments to global scope we need to build them as if 468 * they are global files as well as module 469 */ 470 function containsGlobalScopeAugmentation(sourceFile: SourceFile) { 471 return some(sourceFile.moduleAugmentations, augmentation => isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)); 472 } 473 474 /** 475 * Return true if the file will invalidate all files because it affectes global scope 476 */ 477 function isFileAffectingGlobalScope(sourceFile: SourceFile) { 478 return containsGlobalScopeAugmentation(sourceFile) || 479 !isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile); 480 } 481 482 /** 483 * Gets all files of the program excluding the default library file 484 */ 485 export function getAllFilesExcludingDefaultLibraryFile(state: BuilderState, programOfThisState: Program, firstSourceFile: SourceFile | undefined): readonly SourceFile[] { 486 // Use cached result 487 if (state.allFilesExcludingDefaultLibraryFile) { 488 return state.allFilesExcludingDefaultLibraryFile; 489 } 490 491 let result: SourceFile[] | undefined; 492 if (firstSourceFile) addSourceFile(firstSourceFile); 493 for (const sourceFile of programOfThisState.getSourceFiles()) { 494 if (sourceFile !== firstSourceFile) { 495 addSourceFile(sourceFile); 496 } 497 } 498 state.allFilesExcludingDefaultLibraryFile = result || emptyArray; 499 return state.allFilesExcludingDefaultLibraryFile; 500 501 function addSourceFile(sourceFile: SourceFile) { 502 if (!programOfThisState.isSourceFileDefaultLibrary(sourceFile)) { 503 (result || (result = [])).push(sourceFile); 504 } 505 } 506 } 507 508 /** 509 * When program emits non modular code, gets the files affected by the sourceFile whose shape has changed 510 */ 511 function getFilesAffectedByUpdatedShapeWhenNonModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile) { 512 const compilerOptions = programOfThisState.getCompilerOptions(); 513 // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project, 514 // so returning the file itself is good enough. 515 if (compilerOptions && outFile(compilerOptions)) { 516 return [sourceFileWithUpdatedShape]; 517 } 518 return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); 519 } 520 521 /** 522 * When program emits modular code, gets the files affected by the sourceFile whose shape has changed 523 */ 524 function getFilesAffectedByUpdatedShapeWhenModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile, cacheToUpdateSignature: ESMap<Path, string>, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache: ComputingExportedModulesMap | undefined) { 525 if (isFileAffectingGlobalScope(sourceFileWithUpdatedShape)) { 526 return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); 527 } 528 529 const compilerOptions = programOfThisState.getCompilerOptions(); 530 if (compilerOptions && (compilerOptions.isolatedModules || outFile(compilerOptions))) { 531 return [sourceFileWithUpdatedShape]; 532 } 533 534 // Now we need to if each file in the referencedBy list has a shape change as well. 535 // Because if so, its own referencedBy files need to be saved as well to make the 536 // emitting result consistent with files on disk. 537 const seenFileNamesMap = new Map<Path, SourceFile>(); 538 539 // Start with the paths this file was referenced by 540 seenFileNamesMap.set(sourceFileWithUpdatedShape.resolvedPath, sourceFileWithUpdatedShape); 541 const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.resolvedPath); 542 while (queue.length > 0) { 543 const currentPath = queue.pop()!; 544 if (!seenFileNamesMap.has(currentPath)) { 545 const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath)!; 546 seenFileNamesMap.set(currentPath, currentSourceFile); 547 if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash, exportedModulesMapCache)) { 548 queue.push(...getReferencedByPaths(state, currentSourceFile.resolvedPath)); 549 } 550 } 551 } 552 553 // Return array of values that needs emit 554 return arrayFrom(mapDefinedIterator(seenFileNamesMap.values(), value => value)); 555 } 556 } 557} 558