From 5c55363eec9f6e70c99afd921bcd67799862e45c Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 30 May 2018 13:31:04 -0400 Subject: [PATCH] Fix options caching when ts-loader is used in multiple rules --- src/index.ts | 12 ++++++--- src/interfaces.ts | 2 +- test/execution-tests/optionsCaching/foo.ts | 1 + test/execution-tests/optionsCaching/foo.vue | 7 ++++++ .../optionsCaching/tsconfig.json | 6 +++++ .../optionsCaching/webpack.config.js | 25 +++++++++++++++++++ 6 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 test/execution-tests/optionsCaching/foo.ts create mode 100644 test/execution-tests/optionsCaching/foo.vue create mode 100644 test/execution-tests/optionsCaching/tsconfig.json create mode 100644 test/execution-tests/optionsCaching/webpack.config.js diff --git a/src/index.ts b/src/index.ts index 04e37277b..ab2b00312 100644 --- a/src/index.ts +++ b/src/index.ts @@ -117,15 +117,21 @@ function getLoaderOptions(loader: Webpack) { const instanceName = webpackIndex + '_' + (loaderOptions.instance || 'default'); - if (loaderOptionsCache.hasOwnProperty(instanceName)) { - return loaderOptionsCache[instanceName]; + if (!loaderOptionsCache.hasOwnProperty(instanceName)) { + loaderOptionsCache[instanceName] = new WeakMap(); + } + + const cache = loaderOptionsCache[instanceName]; + + if (cache.has(loaderOptions)) { + return cache.get(loaderOptions) as LoaderOptions; } validateLoaderOptions(loaderOptions); const options = makeLoaderOptions(instanceName, loaderOptions); - loaderOptionsCache[instanceName] = options; + cache.set(loaderOptions, options); return options; } diff --git a/src/interfaces.ts b/src/interfaces.ts index 79207f8ef..a66395fdf 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -258,7 +258,7 @@ export interface TSInstance { } export interface LoaderOptionsCache { - [name: string]: LoaderOptions; + [name: string]: WeakMap; } export interface TSInstances { diff --git a/test/execution-tests/optionsCaching/foo.ts b/test/execution-tests/optionsCaching/foo.ts new file mode 100644 index 000000000..ac5bdfadc --- /dev/null +++ b/test/execution-tests/optionsCaching/foo.ts @@ -0,0 +1 @@ +import './foo.vue' diff --git a/test/execution-tests/optionsCaching/foo.vue b/test/execution-tests/optionsCaching/foo.vue new file mode 100644 index 000000000..f03e3969d --- /dev/null +++ b/test/execution-tests/optionsCaching/foo.vue @@ -0,0 +1,7 @@ +const React = {} + +export default { + render () { + return
hello
+ } +} diff --git a/test/execution-tests/optionsCaching/tsconfig.json b/test/execution-tests/optionsCaching/tsconfig.json new file mode 100644 index 000000000..b6ae463b7 --- /dev/null +++ b/test/execution-tests/optionsCaching/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "esnext", + "jsx": "react" + } +} diff --git a/test/execution-tests/optionsCaching/webpack.config.js b/test/execution-tests/optionsCaching/webpack.config.js new file mode 100644 index 000000000..cec4deaaa --- /dev/null +++ b/test/execution-tests/optionsCaching/webpack.config.js @@ -0,0 +1,25 @@ +var path = require('path') + +module.exports = { + mode: 'development', + entry: path.resolve(__dirname, 'foo.ts'), + output: { + path: __dirname, + filename: 'bundle.js' + }, + module: { + rules: [ + { test: /\.ts$/, loader: 'ts-loader', options: {} }, + { + test: /\.vue$/, + loader: 'ts-loader', + options: { + appendTsxSuffixTo: [/\.vue$/] + } + } + ] + } +} + +// for test harness purposes only, you would not need this in a normal project +module.exports.resolveLoader = { alias: { 'ts-loader': require('path').join(__dirname, "../../../index.js") } }