| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  | import {CustomTransformers, Program} from '@angular/compiler-cli'; | 
					
						
							| 
									
										
										
										
											2019-04-28 00:26:13 +02:00
										 |  |  | import * as api from '@angular/compiler-cli/src/transformers/api'; | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | import * as ts from 'typescript'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 17:54:43 +01:00
										 |  |  | import {createCompilerHost, createProgram} from '../../ngtools2'; | 
					
						
							|  |  |  | import {main, mainDiagnosticsForTest, readNgcCommandLineAndConfiguration} from '../../src/main'; | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  | import {AbsoluteFsPath, FileSystem, NgtscCompilerHost, absoluteFrom, getFileSystem} from '../../src/ngtsc/file_system'; | 
					
						
							|  |  |  | import {Folder, MockFileSystem} from '../../src/ngtsc/file_system/testing'; | 
					
						
							|  |  |  | import {IndexedComponent} from '../../src/ngtsc/indexer'; | 
					
						
							|  |  |  | import {NgtscProgram} from '../../src/ngtsc/program'; | 
					
						
							| 
									
										
										
										
											2018-11-16 17:54:43 +01:00
										 |  |  | import {LazyRoute} from '../../src/ngtsc/routing'; | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  | import {setWrapHostForTest} from '../../src/transformers/compiler_host'; | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Manages a temporary testing directory structure and environment for testing ngtsc by feeding it | 
					
						
							|  |  |  |  * TypeScript code. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export class NgtscTestEnvironment { | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |   private multiCompileHostExt: MultiCompileHostExt|null = null; | 
					
						
							|  |  |  |   private oldProgram: Program|null = null; | 
					
						
							| 
									
										
										
										
											2019-06-27 19:25:00 -04:00
										 |  |  |   private changedResources: Set<string>|null = null; | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |   private constructor( | 
					
						
							|  |  |  |       private fs: FileSystem, readonly outDir: AbsoluteFsPath, readonly basePath: AbsoluteFsPath) {} | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Set up a new testing environment. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |   static setup(files?: Folder): NgtscTestEnvironment { | 
					
						
							|  |  |  |     const fs = getFileSystem(); | 
					
						
							|  |  |  |     if (files !== undefined && fs instanceof MockFileSystem) { | 
					
						
							|  |  |  |       fs.init(files); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     const host = new AugmentedCompilerHost(fs); | 
					
						
							|  |  |  |     setWrapHostForTest(makeWrapHost(host)); | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     const env = new NgtscTestEnvironment(fs, fs.resolve('/built'), absoluteFrom('/')); | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     env.write(absoluteFrom('/tsconfig-base.json'), `{
 | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |       "compilerOptions": { | 
					
						
							| 
									
										
										
										
											2019-02-22 18:06:25 -08:00
										 |  |  |         "emitDecoratorMetadata": true, | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |         "experimentalDecorators": true, | 
					
						
							|  |  |  |         "skipLibCheck": true, | 
					
						
							|  |  |  |         "noImplicitAny": true, | 
					
						
							|  |  |  |         "strictNullChecks": true, | 
					
						
							|  |  |  |         "outDir": "built", | 
					
						
							|  |  |  |         "rootDir": ".", | 
					
						
							|  |  |  |         "baseUrl": ".", | 
					
						
							|  |  |  |         "declaration": true, | 
					
						
							|  |  |  |         "target": "es5", | 
					
						
							| 
									
										
										
										
											2019-01-25 19:49:08 +01:00
										 |  |  |         "newLine": "lf", | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |         "module": "es2015", | 
					
						
							|  |  |  |         "moduleResolution": "node", | 
					
						
							|  |  |  |         "lib": ["es6", "dom"], | 
					
						
							|  |  |  |         "typeRoots": ["node_modules/@types"] | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       "angularCompilerOptions": { | 
					
						
							| 
									
										
										
										
											2019-04-02 11:52:19 -07:00
										 |  |  |         "enableIvy": true, | 
					
						
							|  |  |  |         "ivyTemplateTypeCheck": false | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |       }, | 
					
						
							|  |  |  |       "exclude": [ | 
					
						
							|  |  |  |         "built" | 
					
						
							|  |  |  |       ] | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |     }`);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return env; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assertExists(fileName: string) { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     if (!this.fs.exists(this.fs.resolve(this.outDir, fileName))) { | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |       throw new Error(`Expected ${fileName} to be emitted (outDir: ${this.outDir})`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assertDoesNotExist(fileName: string) { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     if (this.fs.exists(this.fs.resolve(this.outDir, fileName))) { | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |       throw new Error(`Did not expect ${fileName} to be emitted (outDir: ${this.outDir})`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getContents(fileName: string): string { | 
					
						
							|  |  |  |     this.assertExists(fileName); | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     const modulePath = this.fs.resolve(this.outDir, fileName); | 
					
						
							|  |  |  |     return this.fs.readFile(modulePath); | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |   enableMultipleCompilations(): void { | 
					
						
							| 
									
										
										
										
											2019-06-10 16:22:56 +01:00
										 |  |  |     this.changedResources = new Set(); | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     this.multiCompileHostExt = new MultiCompileHostExt(this.fs); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     setWrapHostForTest(makeWrapHost(this.multiCompileHostExt)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   flushWrittenFileTracking(): void { | 
					
						
							|  |  |  |     if (this.multiCompileHostExt === null) { | 
					
						
							|  |  |  |       throw new Error(`Not tracking written files - call enableMultipleCompilations()`); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-10 16:22:56 +01:00
										 |  |  |     this.changedResources !.clear(); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     this.multiCompileHostExt.flushWrittenFileTracking(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 19:25:00 -04:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Older versions of the CLI do not provide the `CompilerHost.getModifiedResourceFiles()` method. | 
					
						
							|  |  |  |    * This results in the `changedResources` set being `null`. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   simulateLegacyCLICompilerHost() { this.changedResources = null; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |   getFilesWrittenSinceLastFlush(): Set<string> { | 
					
						
							|  |  |  |     if (this.multiCompileHostExt === null) { | 
					
						
							|  |  |  |       throw new Error(`Not tracking written files - call enableMultipleCompilations()`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const writtenFiles = new Set<string>(); | 
					
						
							|  |  |  |     this.multiCompileHostExt.getFilesWrittenSinceLastFlush().forEach(rawFile => { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |       if (rawFile.startsWith(this.outDir)) { | 
					
						
							|  |  |  |         writtenFiles.add(rawFile.substr(this.outDir.length)); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     return writtenFiles; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   write(fileName: string, content: string) { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     const absFilePath = this.fs.resolve(this.basePath, fileName); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     if (this.multiCompileHostExt !== null) { | 
					
						
							|  |  |  |       this.multiCompileHostExt.invalidate(absFilePath); | 
					
						
							| 
									
										
										
										
											2019-06-10 16:22:56 +01:00
										 |  |  |       this.changedResources !.add(absFilePath); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     this.fs.ensureDir(this.fs.dirname(absFilePath)); | 
					
						
							|  |  |  |     this.fs.writeFile(absFilePath, content); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   invalidateCachedFile(fileName: string): void { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     const absFilePath = this.fs.resolve(this.basePath, fileName); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     if (this.multiCompileHostExt === null) { | 
					
						
							|  |  |  |       throw new Error(`Not caching files - call enableMultipleCompilations()`); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     this.multiCompileHostExt.invalidate(absFilePath); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-30 10:37:06 -08:00
										 |  |  |   tsconfig(extraOpts: {[key: string]: string | boolean} = {}, extraRootDirs?: string[]): void { | 
					
						
							|  |  |  |     const tsconfig: {[key: string]: any} = { | 
					
						
							|  |  |  |       extends: './tsconfig-base.json', | 
					
						
							| 
									
										
										
										
											2019-02-08 11:37:21 +00:00
										 |  |  |       angularCompilerOptions: {...extraOpts, enableIvy: true}, | 
					
						
							| 
									
										
										
										
											2018-11-30 10:37:06 -08:00
										 |  |  |     }; | 
					
						
							|  |  |  |     if (extraRootDirs !== undefined) { | 
					
						
							|  |  |  |       tsconfig.compilerOptions = { | 
					
						
							|  |  |  |         rootDirs: ['.', ...extraRootDirs], | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     this.write('tsconfig.json', JSON.stringify(tsconfig, null, 2)); | 
					
						
							| 
									
										
										
										
											2019-02-19 17:36:26 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (extraOpts['_useHostForImportGeneration'] === true) { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |       setWrapHostForTest(makeWrapHost(new FileNameToModuleNameHost(this.fs))); | 
					
						
							| 
									
										
										
										
											2019-02-19 17:36:26 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Run the compiler to completion, and assert that no errors occurred. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-01-03 12:23:00 +02:00
										 |  |  |   driveMain(customTransformers?: CustomTransformers): void { | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |     const errorSpy = jasmine.createSpy('consoleError').and.callFake(console.error); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     let reuseProgram: {program: Program | undefined}|undefined = undefined; | 
					
						
							|  |  |  |     if (this.multiCompileHostExt !== null) { | 
					
						
							|  |  |  |       reuseProgram = { | 
					
						
							|  |  |  |         program: this.oldProgram || undefined, | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-10 16:22:56 +01:00
										 |  |  |     const exitCode = main( | 
					
						
							|  |  |  |         ['-p', this.basePath], errorSpy, undefined, customTransformers, reuseProgram, | 
					
						
							|  |  |  |         this.changedResources); | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |     expect(errorSpy).not.toHaveBeenCalled(); | 
					
						
							|  |  |  |     expect(exitCode).toBe(0); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     if (this.multiCompileHostExt !== null) { | 
					
						
							|  |  |  |       this.oldProgram = reuseProgram !.program !; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Run the compiler to completion, and return any `ts.Diagnostic` errors that may have occurred. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-04-28 00:26:13 +02:00
										 |  |  |   driveDiagnostics(): ReadonlyArray<ts.Diagnostic|api.Diagnostic> { | 
					
						
							|  |  |  |     return mainDiagnosticsForTest(['-p', this.basePath]); | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 17:54:43 +01:00
										 |  |  |   driveRoutes(entryPoint?: string): LazyRoute[] { | 
					
						
							|  |  |  |     const {rootNames, options} = readNgcCommandLineAndConfiguration(['-p', this.basePath]); | 
					
						
							|  |  |  |     const host = createCompilerHost({options}); | 
					
						
							|  |  |  |     const program = createProgram({rootNames, host, options}); | 
					
						
							|  |  |  |     return program.listLazyRoutes(entryPoint); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   driveIndexer(): Map<ts.Declaration, IndexedComponent> { | 
					
						
							|  |  |  |     const {rootNames, options} = readNgcCommandLineAndConfiguration(['-p', this.basePath]); | 
					
						
							|  |  |  |     const host = createCompilerHost({options}); | 
					
						
							|  |  |  |     const program = createProgram({rootNames, host, options}); | 
					
						
							|  |  |  |     return (program as NgtscProgram).getIndexedComponents(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-09-25 15:35:03 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  | class AugmentedCompilerHost extends NgtscCompilerHost { | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |   delegate !: ts.CompilerHost; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FileNameToModuleNameHost extends AugmentedCompilerHost { | 
					
						
							|  |  |  |   fileNameToModuleName(importedFilePath: string): string { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     const relativeFilePath = this.fs.relative(this.fs.pwd(), this.fs.resolve(importedFilePath)); | 
					
						
							|  |  |  |     const rootedPath = this.fs.join('root', relativeFilePath); | 
					
						
							|  |  |  |     return rootedPath.replace(/(\.d)?.ts$/, ''); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MultiCompileHostExt extends AugmentedCompilerHost implements Partial<ts.CompilerHost> { | 
					
						
							|  |  |  |   private cache = new Map<string, ts.SourceFile>(); | 
					
						
							|  |  |  |   private writtenFiles = new Set<string>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getSourceFile( | 
					
						
							|  |  |  |       fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void, | 
					
						
							|  |  |  |       shouldCreateNewSourceFile?: boolean): ts.SourceFile|undefined { | 
					
						
							|  |  |  |     if (this.cache.has(fileName)) { | 
					
						
							|  |  |  |       return this.cache.get(fileName) !; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     const sf = super.getSourceFile(fileName, languageVersion); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     if (sf !== undefined) { | 
					
						
							|  |  |  |       this.cache.set(sf.fileName, sf); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return sf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   flushWrittenFileTracking(): void { this.writtenFiles.clear(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   writeFile( | 
					
						
							|  |  |  |       fileName: string, data: string, writeByteOrderMark: boolean, | 
					
						
							|  |  |  |       onError: ((message: string) => void)|undefined, | 
					
						
							|  |  |  |       sourceFiles?: ReadonlyArray<ts.SourceFile>): void { | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     super.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); | 
					
						
							| 
									
										
										
										
											2019-03-18 11:21:29 -07:00
										 |  |  |     this.writtenFiles.add(fileName); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getFilesWrittenSinceLastFlush(): Set<string> { return this.writtenFiles; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   invalidate(fileName: string): void { this.cache.delete(fileName); } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function makeWrapHost(wrapped: AugmentedCompilerHost): (host: ts.CompilerHost) => ts.CompilerHost { | 
					
						
							|  |  |  |   return (delegate) => { | 
					
						
							|  |  |  |     wrapped.delegate = delegate; | 
					
						
							|  |  |  |     return new Proxy(delegate, { | 
					
						
							|  |  |  |       get: (target: ts.CompilerHost, name: string): any => { | 
					
						
							|  |  |  |         if ((wrapped as any)[name] !== undefined) { | 
					
						
							|  |  |  |           return (wrapped as any)[name] !.bind(wrapped); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return (target as any)[name]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } |