diff --git a/CHANGELOG.md b/CHANGELOG.md index 122e0dc5a..810283ee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## v8.3.0 + +* [Fixed impossibility to have several instances of ts-loader with different compiler options](https://github.com/TypeStrong/ts-loader/issues/1316) - thanks @timocov +* This is a backport from v9.2.0 for webpack 4 compatibility + +## v8.2.0 + +* [Use caches for module resolution and type reference directives when using compiler default functions](https://github.com/TypeStrong/ts-loader/pull/1287) - thanks @sheetalkamat - uses: https://github.com/microsoft/TypeScript/pull/43700 +* This is a backport from v9.1.0 for webpack 4 compatibility + ## v8.1.0 * [feat: remove top-level typescript import statements](https://github.com/TypeStrong/ts-loader/pull/1259) - thanks @ulivz diff --git a/package.json b/package.json index 55ad0e6e8..a1e2866a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ts-loader", - "version": "8.1.0", + "version": "8.3.0", "description": "TypeScript loader for webpack", "main": "index.js", "types": "dist", @@ -96,7 +96,7 @@ "mocha": "^6.0.0", "prettier": "^2.0.5", "rimraf": "^2.6.2", - "typescript": "^4.0.0", + "typescript": "^4.6.3", "webpack": "^4.5.0", "webpack-cli": "^3.1.1" }, diff --git a/src/index.ts b/src/index.ts index ac3502a2c..aaea09336 100644 --- a/src/index.ts +++ b/src/index.ts @@ -161,8 +161,10 @@ function getOptionsHash(loaderOptions: LoaderOptions) { const hash = crypto.createHash('sha256'); Object.keys(loaderOptions).forEach(key => { const value = loaderOptions[key]; - if (value) { - hash.update(key + value.toString()); + if (value !== undefined) { + const valueString = + typeof value === 'function' ? value.toString() : JSON.stringify(value); + hash.update(key + valueString); } }); return hash.digest('hex').substring(0, 16); diff --git a/src/instances.ts b/src/instances.ts index aaa36b792..b92e2f9ca 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -378,6 +378,7 @@ export function initializeInstance( } else if (typeof customerTransformers === 'string') { try { customerTransformers = require(customerTransformers); + // eslint-disable-next-line prettier/prettier } catch (err) { throw new Error( `Failed to load customTransformers from "${instance.loaderOptions.getCustomTransformers}": ${err.message}` diff --git a/src/interfaces.ts b/src/interfaces.ts index f2bf5a4b5..6d9cc06d7 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -102,8 +102,9 @@ export interface ServiceHostWhichMayBeCacheable export interface WatchHost extends typescript.WatchCompilerHostOfFilesAndCompilerOptions< - typescript.EmitAndSemanticDiagnosticsBuilderProgram - > { + typescript.EmitAndSemanticDiagnosticsBuilderProgram + >, + HostMayBeCacheable { invokeFileWatcher: WatchFactory['invokeFileWatcher']; updateRootFileNames(): void; outputFiles: Map; @@ -178,6 +179,48 @@ export interface ConfigFileInfo { dtsFiles?: string[]; } +interface CacheWithRedirects { + ownMap: Map; + redirectsMap: Map>; + getOrCreateMapOfCacheRedirects( + redirectedReference: typescript.ResolvedProjectReference | undefined + ): Map; + clear(): void; + setOwnOptions(newOptions: typescript.CompilerOptions): void; + setOwnMap(newOwnMap: Map): void; +} +interface PerModuleNameCache { + get( + directory: string + ): typescript.ResolvedModuleWithFailedLookupLocations | undefined; + set( + directory: string, + result: typescript.ResolvedModuleWithFailedLookupLocations + ): void; +} + +export interface ModuleResolutionCache + extends typescript.ModuleResolutionCache { + directoryToModuleNameMap: CacheWithRedirects< + Map + >; + moduleNameToDirectoryMap: CacheWithRedirects; + clear(): void; + update(compilerOptions: typescript.CompilerOptions): void; +} + +// Until the API has been released and ts-loader is built against a version of TypeScript that contains it - see https://github.com/microsoft/TypeScript/blob/74993a2a64bb2e423b40204bb54ff749cdd4ef54/src/compiler/moduleNameResolver.ts#L458 +export interface TypeReferenceDirectiveResolutionCache { + getOrCreateCacheForDirectory( + directoryName: string, + redirectedReference?: typescript.ResolvedProjectReference + ): Map< + string, + typescript.ResolvedTypeReferenceDirectiveWithFailedLookupLocations + >; + clear(): void; + update(compilerOptions: typescript.CompilerOptions): void; +} export interface TSInstance { compiler: typeof typescript; compilerOptions: typescript.CompilerOptions; @@ -185,6 +228,8 @@ export interface TSInstance { appendTsTsxSuffixesIfRequired: (filePath: string) => string; loaderOptions: LoaderOptions; rootFileNames: Set; + moduleResolutionCache?: ModuleResolutionCache; + typeReferenceResolutionCache?: TypeReferenceDirectiveResolutionCache; /** * a cache of all the files */ diff --git a/src/servicesHost.ts b/src/servicesHost.ts index d44dce8b7..3125bc7a0 100644 --- a/src/servicesHost.ts +++ b/src/servicesHost.ts @@ -10,6 +10,7 @@ import { CustomResolveModuleName, CustomResolveTypeReferenceDirective, FilePathKey, + ModuleResolutionCache, ModuleResolutionHostMayBeCacheable, ResolvedModule, ResolveSync, @@ -248,39 +249,19 @@ function makeResolvers( scriptRegex: RegExp, instance: TSInstance ) { - const resolveTypeReferenceDirective = makeResolveTypeReferenceDirective( - compiler, - compilerOptions, - moduleResolutionHost, - customResolveTypeReferenceDirective - ); - - const resolveTypeReferenceDirectives = ( - typeDirectiveNames: string[], - containingFile: string, - _redirectedReference?: typescript.ResolvedProjectReference - ): (typescript.ResolvedTypeReferenceDirective | undefined)[] => - typeDirectiveNames.map( - directive => - resolveTypeReferenceDirective( - directive, - containingFile, - _redirectedReference - ).resolvedTypeReferenceDirective - ); - const resolveModuleName = makeResolveModuleName( compiler, compilerOptions, moduleResolutionHost, - customResolveModuleName + customResolveModuleName, + instance ); const resolveModuleNames = ( moduleNames: string[], containingFile: string, _reusedNames?: string[] | undefined, - _redirectedReference?: typescript.ResolvedProjectReference | undefined + redirectedReference?: typescript.ResolvedProjectReference | undefined ): (typescript.ResolvedModule | undefined)[] => { const resolvedModules = moduleNames.map(moduleName => resolveModule( @@ -289,7 +270,8 @@ function makeResolvers( appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, - containingFile + containingFile, + redirectedReference ) ); @@ -298,6 +280,28 @@ function makeResolvers( return resolvedModules; }; + const resolveTypeReferenceDirective = makeResolveTypeReferenceDirective( + compiler, + compilerOptions, + moduleResolutionHost, + customResolveTypeReferenceDirective, + instance + ); + + const resolveTypeReferenceDirectives = ( + typeDirectiveNames: string[], + containingFile: string, + redirectedReference?: typescript.ResolvedProjectReference + ): (typescript.ResolvedTypeReferenceDirective | undefined)[] => + typeDirectiveNames.map( + directive => + resolveTypeReferenceDirective( + directive, + containingFile, + redirectedReference + ).resolvedTypeReferenceDirective + ); + return { resolveTypeReferenceDirectives, resolveModuleNames, @@ -493,7 +497,7 @@ export function makeWatchHost( fileName => files.has(filePathKeyMapper(fileName)) || compiler.sys.fileExists(fileName), - /*enabledCaching*/ false + instance.loaderOptions.experimentalFileCaching ); const watchHost: WatchHost = { @@ -601,6 +605,60 @@ export function makeWatchHost( const missingFileModifiedTime = new Date(0); +function identity(x: T) { + return x; +} +function toLowerCase(x: string) { + return x.toLowerCase(); +} +const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g; +function toFileNameLowerCase(x: string) { + return fileNameLowerCaseRegExp.test(x) + ? x.replace(fileNameLowerCaseRegExp, toLowerCase) + : x; +} +function createGetCanonicalFileName(instance: TSInstance) { + return useCaseSensitiveFileNames(instance.compiler, instance.loaderOptions) + ? identity + : toFileNameLowerCase; +} + +function createModuleResolutionCache( + instance: TSInstance, + moduleResolutionHost: typescript.ModuleResolutionHost +): ModuleResolutionCache { + const cache = instance.compiler.createModuleResolutionCache( + moduleResolutionHost.getCurrentDirectory!(), + createGetCanonicalFileName(instance), + instance.compilerOptions + ) as ModuleResolutionCache; + // Add new API optional methods + if (!cache.clear) { + cache.clear = () => { + cache.directoryToModuleNameMap.clear(); + cache.moduleNameToDirectoryMap.clear(); + }; + } + if (!cache.update) { + cache.update = options => { + if (!options.configFile) return; + const ref: typescript.ResolvedProjectReference = { + sourceFile: options.configFile! as typescript.TsConfigSourceFile, + commandLine: { options } as typescript.ParsedCommandLine, + }; + cache.directoryToModuleNameMap.setOwnMap( + cache.directoryToModuleNameMap.getOrCreateMapOfCacheRedirects(ref) + ); + cache.moduleNameToDirectoryMap.setOwnMap( + cache.moduleNameToDirectoryMap.getOrCreateMapOfCacheRedirects(ref) + ); + cache.directoryToModuleNameMap.setOwnOptions(options); + cache.moduleNameToDirectoryMap.setOwnOptions(options); + }; + } + return cache; +} + /** * Create the TypeScript Watch host */ @@ -618,12 +676,7 @@ export function makeSolutionBuilderHost( // loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3 const formatDiagnosticHost: typescript.FormatDiagnosticsHost = { getCurrentDirectory: compiler.sys.getCurrentDirectory, - getCanonicalFileName: useCaseSensitiveFileNames( - compiler, - instance.loaderOptions - ) - ? s => s - : s => s.toLowerCase(), + getCanonicalFileName: createGetCanonicalFileName(instance), getNewLine: () => compiler.sys.newLine, }; @@ -706,6 +759,28 @@ export function makeSolutionBuilderHost( const solutionBuilderHost: SolutionBuilderWithWatchHost = { ...sysHost, ...moduleResolutionHost, + createProgram: ( + rootNames, + options, + host, + oldProgram, + configFileParsingDiagnostics, + projectReferences + ) => { + instance.moduleResolutionCache?.update(options || {}); + instance.typeReferenceResolutionCache?.update(options || {}); + const result = sysHost.createProgram( + rootNames, + options, + host, + oldProgram, + configFileParsingDiagnostics, + projectReferences + ); + instance.typeReferenceResolutionCache?.update(instance.compilerOptions); + instance.moduleResolutionCache?.update(instance.compilerOptions); + return result; + }, resolveModuleNames, resolveTypeReferenceDirectives, diagnostics, @@ -1092,16 +1167,31 @@ function makeResolveTypeReferenceDirective( moduleResolutionHost: typescript.ModuleResolutionHost, customResolveTypeReferenceDirective: | CustomResolveTypeReferenceDirective - | undefined + | undefined, + instance: TSInstance ): ResolveTypeReferenceDirective { if (customResolveTypeReferenceDirective === undefined) { + // Until the api is published + if ( + (compiler as any).createTypeReferenceDirectiveResolutionCache && + !instance.typeReferenceResolutionCache + ) { + instance.typeReferenceResolutionCache = (compiler as any).createTypeReferenceDirectiveResolutionCache( + moduleResolutionHost.getCurrentDirectory!(), + createGetCanonicalFileName(instance), + instance.compilerOptions, + instance.moduleResolutionCache?.getPackageJsonInfoCache?.() + ); + } return (directive, containingFile, redirectedReference) => - compiler.resolveTypeReferenceDirective( + // Until the api is published + (compiler.resolveTypeReferenceDirective as any)( directive, containingFile, compilerOptions, moduleResolutionHost, - redirectedReference + redirectedReference, + instance.typeReferenceResolutionCache ); } @@ -1131,7 +1221,8 @@ function resolveModule( appendTsTsxSuffixesIfRequired: (filePath: string) => string, scriptRegex: RegExp, moduleName: string, - containingFile: string + containingFile: string, + redirectedReference: typescript.ResolvedProjectReference | undefined ) { let resolutionResult: ResolvedModule; @@ -1149,16 +1240,19 @@ function resolveModule( } } catch (e) {} - const tsResolution = resolveModuleName(moduleName, containingFile); + const tsResolution = resolveModuleName( + moduleName, + containingFile, + redirectedReference + ); if (tsResolution.resolvedModule !== undefined) { const resolvedFileName = path.normalize( tsResolution.resolvedModule.resolvedFileName ); const tsResolutionResult: ResolvedModule = { + ...tsResolution.resolvedModule, originalFileName: resolvedFileName, resolvedFileName, - isExternalLibraryImport: - tsResolution.resolvedModule.isExternalLibraryImport, }; return resolutionResult! === undefined || @@ -1173,26 +1267,36 @@ function resolveModule( type ResolveModuleName = ( moduleName: string, - containingFile: string + containingFile: string, + redirectedReference: typescript.ResolvedProjectReference | undefined ) => typescript.ResolvedModuleWithFailedLookupLocations; function makeResolveModuleName( compiler: typeof typescript, compilerOptions: typescript.CompilerOptions, moduleResolutionHost: typescript.ModuleResolutionHost, - customResolveModuleName: CustomResolveModuleName | undefined + customResolveModuleName: CustomResolveModuleName | undefined, + instance: TSInstance ): ResolveModuleName { if (customResolveModuleName === undefined) { - return (moduleName: string, containingFile: string) => + if (!instance.moduleResolutionCache) { + instance.moduleResolutionCache = createModuleResolutionCache( + instance, + moduleResolutionHost + ); + } + return (moduleName, containingFile, redirectedReference) => compiler.resolveModuleName( moduleName, containingFile, compilerOptions, - moduleResolutionHost + moduleResolutionHost, + instance.moduleResolutionCache, + redirectedReference ); } - return (moduleName: string, containingFile: string) => + return (moduleName, containingFile) => customResolveModuleName( moduleName, containingFile, diff --git a/src/watch-run.ts b/src/watch-run.ts index 69b9e0c6d..f117979f7 100644 --- a/src/watch-run.ts +++ b/src/watch-run.ts @@ -22,6 +22,9 @@ export function makeWatchRun( return (compiler: webpack.Compiler, callback: (err?: Error) => void) => { instance.servicesHost?.clearCache?.(); + instance.watchHost?.clearCache?.(); + instance.moduleResolutionCache?.clear(); + instance.typeReferenceResolutionCache?.clear(); const promises = []; if (instance.loaderOptions.transpileOnly) { instance.reportTranspileErrors = true; diff --git a/test/comparison-tests/instance/expectedOutput-4.1/output.txt b/test/comparison-tests/instance/expectedOutput-4.1/output.txt index 09690c0b5..1167dfee7 100644 --- a/test/comparison-tests/instance/expectedOutput-4.1/output.txt +++ b/test/comparison-tests/instance/expectedOutput-4.1/output.txt @@ -1,19 +1,19 @@ - Asset Size Chunks Chunk Names -bundle.js 4 KiB a [emitted] a + Asset Size Chunks Chunk Names +bundle.js 4.01 KiB a [emitted] a Entrypoint a = bundle.js Entrypoint b = -[./a.ts] 276 bytes {a} [built] [failed] [1 error] -[./b.ts] 276 bytes {b} [built] [failed] [1 error] +[./a.ts] 273 bytes {a} [built] [failed] [1 error] +[./b.ts] 273 bytes {b} [built] [failed] [1 error] ERROR in ./a.ts -Module build failed (from index.js): +Module build failed (from /index.js): Error: A file specified in tsconfig.json could not be found: i-dont-exist - at Object.loader (dist/index.js:18:18) + at Object.loader (dist\index.js:18:18) ERROR in ./b.ts -Module build failed (from index.js): +Module build failed (from /index.js): Error: A file specified in tsconfig.json could not be found: i-dont-exist - at Object.loader (dist/index.js:18:18) + at Object.loader (dist\index.js:18:18) ERROR in chunk b [entry] bundle.js diff --git a/test/comparison-tests/instance/expectedOutput-transpile-4.1/output.txt b/test/comparison-tests/instance/expectedOutput-transpile-4.1/output.txt index 1da55bdfe..41b0bbbb8 100644 --- a/test/comparison-tests/instance/expectedOutput-transpile-4.1/output.txt +++ b/test/comparison-tests/instance/expectedOutput-transpile-4.1/output.txt @@ -1,19 +1,19 @@ Asset Size Chunks Chunk Names -bundle.js 4.01 KiB a [emitted] a +bundle.js 4.02 KiB a [emitted] a Entrypoint a = bundle.js Entrypoint b = -[./a.ts] 286 bytes {a} [built] [failed] [1 error] -[./b.ts] 286 bytes {b} [built] [failed] [1 error] +[./a.ts] 283 bytes {a} [built] [failed] [1 error] +[./b.ts] 283 bytes {b} [built] [failed] [1 error] ERROR in ./a.ts -Module build failed (from index.js): +Module build failed (from /index.js): Error: A file specified in tsconfig.json could not be found: i-dont-exist - at Object.loader (dist/index.js:18:18) + at Object.loader (dist\index.js:18:18) ERROR in ./b.ts -Module build failed (from index.js): +Module build failed (from /index.js): Error: A file specified in tsconfig.json could not be found: i-dont-exist - at Object.loader (dist/index.js:18:18) + at Object.loader (dist\index.js:18:18) ERROR in chunk b [entry] bundle.js diff --git a/test/comparison-tests/loaderOptionsCaching/app.ts b/test/comparison-tests/loaderOptionsCaching/app.ts new file mode 100644 index 000000000..fbb9debdf --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/app.ts @@ -0,0 +1,2 @@ +import './submodule-es5'; +import './submodule-es6'; diff --git a/test/comparison-tests/loaderOptionsCaching/expectedOutput-4.1/bundle.js b/test/comparison-tests/loaderOptionsCaching/expectedOutput-4.1/bundle.js new file mode 100644 index 000000000..9dd55846a --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/expectedOutput-4.1/bundle.js @@ -0,0 +1,123 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./app.ts"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./app.ts": +/*!****************!*\ + !*** ./app.ts ***! + \****************/ +/*! no exports provided */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _submodule_es5__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./submodule-es5 */ \"./submodule-es5/index.ts\");\n/* harmony import */ var _submodule_es5__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_submodule_es5__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _submodule_es6__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./submodule-es6 */ \"./submodule-es6/index.ts\");\n/* harmony import */ var _submodule_es6__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_submodule_es6__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\n\n//# sourceURL=webpack:///./app.ts?"); + +/***/ }), + +/***/ "./submodule-es5/index.ts": +/*!********************************!*\ + !*** ./submodule-es5/index.ts ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("var string = 'Hello from es5 file';\r\nconsole.log(string);\r\n\n\n//# sourceURL=webpack:///./submodule-es5/index.ts?"); + +/***/ }), + +/***/ "./submodule-es6/index.ts": +/*!********************************!*\ + !*** ./submodule-es6/index.ts ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("const set = new Set([42]);\r\nfor (const value of set) {\r\n console.log(value);\r\n}\r\nconst string = 'Hello from es6 file';\r\nconsole.log(string);\r\n\n\n//# sourceURL=webpack:///./submodule-es6/index.ts?"); + +/***/ }) + +/******/ }); \ No newline at end of file diff --git a/test/comparison-tests/loaderOptionsCaching/expectedOutput-4.1/output.txt b/test/comparison-tests/loaderOptionsCaching/expectedOutput-4.1/output.txt new file mode 100644 index 000000000..48c547f8d --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/expectedOutput-4.1/output.txt @@ -0,0 +1,6 @@ + Asset Size Chunks Chunk Names +bundle.js 5.21 KiB main [emitted] main +Entrypoint main = bundle.js +[./app.ts] 52 bytes {main} [built] +[./submodule-es5/index.ts] 59 bytes {main} [built] +[./submodule-es6/index.ts] 145 bytes {main} [built] \ No newline at end of file diff --git a/test/comparison-tests/loaderOptionsCaching/expectedOutput-transpile-4.1/bundle.js b/test/comparison-tests/loaderOptionsCaching/expectedOutput-transpile-4.1/bundle.js new file mode 100644 index 000000000..9dd55846a --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/expectedOutput-transpile-4.1/bundle.js @@ -0,0 +1,123 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./app.ts"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./app.ts": +/*!****************!*\ + !*** ./app.ts ***! + \****************/ +/*! no exports provided */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _submodule_es5__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./submodule-es5 */ \"./submodule-es5/index.ts\");\n/* harmony import */ var _submodule_es5__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_submodule_es5__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _submodule_es6__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./submodule-es6 */ \"./submodule-es6/index.ts\");\n/* harmony import */ var _submodule_es6__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_submodule_es6__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\n\n//# sourceURL=webpack:///./app.ts?"); + +/***/ }), + +/***/ "./submodule-es5/index.ts": +/*!********************************!*\ + !*** ./submodule-es5/index.ts ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("var string = 'Hello from es5 file';\r\nconsole.log(string);\r\n\n\n//# sourceURL=webpack:///./submodule-es5/index.ts?"); + +/***/ }), + +/***/ "./submodule-es6/index.ts": +/*!********************************!*\ + !*** ./submodule-es6/index.ts ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("const set = new Set([42]);\r\nfor (const value of set) {\r\n console.log(value);\r\n}\r\nconst string = 'Hello from es6 file';\r\nconsole.log(string);\r\n\n\n//# sourceURL=webpack:///./submodule-es6/index.ts?"); + +/***/ }) + +/******/ }); \ No newline at end of file diff --git a/test/comparison-tests/loaderOptionsCaching/expectedOutput-transpile-4.1/output.txt b/test/comparison-tests/loaderOptionsCaching/expectedOutput-transpile-4.1/output.txt new file mode 100644 index 000000000..48c547f8d --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/expectedOutput-transpile-4.1/output.txt @@ -0,0 +1,6 @@ + Asset Size Chunks Chunk Names +bundle.js 5.21 KiB main [emitted] main +Entrypoint main = bundle.js +[./app.ts] 52 bytes {main} [built] +[./submodule-es5/index.ts] 59 bytes {main} [built] +[./submodule-es6/index.ts] 145 bytes {main} [built] \ No newline at end of file diff --git a/test/comparison-tests/loaderOptionsCaching/submodule-es5/index.ts b/test/comparison-tests/loaderOptionsCaching/submodule-es5/index.ts new file mode 100644 index 000000000..23c844e8a --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/submodule-es5/index.ts @@ -0,0 +1,2 @@ +const string = 'Hello from es5 file'; +console.log(string); diff --git a/test/comparison-tests/loaderOptionsCaching/submodule-es5/tsconfig.json b/test/comparison-tests/loaderOptionsCaching/submodule-es5/tsconfig.json new file mode 100644 index 000000000..fa3e10a3d --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/submodule-es5/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "target": "es5" + } +} diff --git a/test/comparison-tests/loaderOptionsCaching/submodule-es6/index.ts b/test/comparison-tests/loaderOptionsCaching/submodule-es6/index.ts new file mode 100644 index 000000000..f59c741a4 --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/submodule-es6/index.ts @@ -0,0 +1,7 @@ +const set = new Set([42]); +for (const value of set) { + console.log(value); +} + +const string = 'Hello from es6 file'; +console.log(string); diff --git a/test/comparison-tests/loaderOptionsCaching/submodule-es6/tsconfig.json b/test/comparison-tests/loaderOptionsCaching/submodule-es6/tsconfig.json new file mode 100644 index 000000000..ea71f9415 --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/submodule-es6/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "target": "es6" + } +} \ No newline at end of file diff --git a/test/comparison-tests/loaderOptionsCaching/tsconfig.json b/test/comparison-tests/loaderOptionsCaching/tsconfig.json new file mode 100644 index 000000000..fa3e10a3d --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "target": "es5" + } +} diff --git a/test/comparison-tests/loaderOptionsCaching/webpack.config.js b/test/comparison-tests/loaderOptionsCaching/webpack.config.js new file mode 100644 index 000000000..82a2f161b --- /dev/null +++ b/test/comparison-tests/loaderOptionsCaching/webpack.config.js @@ -0,0 +1,32 @@ +module.exports = { + mode: 'development', + entry: './app.ts', + output: { + filename: 'bundle.js' + }, + resolve: { + extensions: ['.ts'] + }, + module: { + rules: [ + { + test: /submodule-es6.*\.ts$/, + loader: 'ts-loader', + options: { + compilerOptions: { + target: 'es6', + }, + }, + }, + { + test: /submodule-es5.*\.ts$/, + loader: 'ts-loader', + options: { + compilerOptions: { + target: 'es5', + }, + }, + } + ] + } +} diff --git a/test/comparison-tests/projectReferencesSymLinks/expectedOutput-4.1/patch0/output.txt b/test/comparison-tests/projectReferencesSymLinks/expectedOutput-4.1/patch0/output.txt index 86ba1eac3..ab18dd44d 100644 --- a/test/comparison-tests/projectReferencesSymLinks/expectedOutput-4.1/patch0/output.txt +++ b/test/comparison-tests/projectReferencesSymLinks/expectedOutput-4.1/patch0/output.txt @@ -11,4 +11,4 @@ Entrypoint main = index.js ERROR in app/src/index.ts ./src/index.ts 1:9-25 [tsl] ERROR in app/src/index.ts(1,10) - TS2724: '"../../lib/dist"' has no exported member named 'getMeaningOfLife'. Did you mean 'getMeaningOfLife3'? \ No newline at end of file + TS2724: '"../../node_modules/lib/dist"' has no exported member named 'getMeaningOfLife'. Did you mean 'getMeaningOfLife3'? \ No newline at end of file diff --git a/test/comparison-tests/projectReferencesSymLinks_WatchApi/expectedOutput-4.1/patch0/output.txt b/test/comparison-tests/projectReferencesSymLinks_WatchApi/expectedOutput-4.1/patch0/output.txt index 86ba1eac3..ab18dd44d 100644 --- a/test/comparison-tests/projectReferencesSymLinks_WatchApi/expectedOutput-4.1/patch0/output.txt +++ b/test/comparison-tests/projectReferencesSymLinks_WatchApi/expectedOutput-4.1/patch0/output.txt @@ -11,4 +11,4 @@ Entrypoint main = index.js ERROR in app/src/index.ts ./src/index.ts 1:9-25 [tsl] ERROR in app/src/index.ts(1,10) - TS2724: '"../../lib/dist"' has no exported member named 'getMeaningOfLife'. Did you mean 'getMeaningOfLife3'? \ No newline at end of file + TS2724: '"../../node_modules/lib/dist"' has no exported member named 'getMeaningOfLife'. Did you mean 'getMeaningOfLife3'? \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index ea6e337a9..f078dd007 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6267,10 +6267,10 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" - integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== +typescript@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" + integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== uglify-js@3.3.x: version "3.3.9"