From 04c8eb0fede29c331d30bd5288ffaf2c4a1c98e7 Mon Sep 17 00:00:00 2001 From: Kevin Decker Date: Sat, 20 Jun 2020 22:45:32 -0500 Subject: [PATCH 1/3] Add support for imported exports Adds support for ``` export * from 'module'; export { function } from 'module' ``` providedExports field appears to be around for all of Webpack 4. If prior webpacks are supported still, then will need a simple adapter layer. --- src/index.js | 7 ++++++- test/src/and-the-other.js | 9 +++++++++ test/src/common.js | 3 +++ test/src/index.test.js | 21 +++++++++++++++++++++ test/src/other.js | 6 ++++-- test/src/worker.js | 6 ++++++ 6 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 test/src/and-the-other.js create mode 100644 test/src/common.js diff --git a/src/index.js b/src/index.js index db75312..01b019d 100644 --- a/src/index.js +++ b/src/index.js @@ -128,7 +128,12 @@ loader.pitch = function(request) { let key = entries[0].entryModule.nameForCondition(); let contents = compilation.assets[worker.file].source(); - let exports = Object.keys(CACHE[key] || {}); + let exports = Array.from( + new Set([ + ...Object.keys(CACHE[key] || {}), + ...entries[0].entryModule.buildMeta.providedExports + ]) + ); // console.log('Workerized exports: ', exports.join(', ')); diff --git a/test/src/and-the-other.js b/test/src/and-the-other.js new file mode 100644 index 0000000..c9ece14 --- /dev/null +++ b/test/src/and-the-other.js @@ -0,0 +1,9 @@ +export function otherOtherFoo() { + return 2; +} + +export function anyFoo() { + return 4; +} + +export const otherOtherBar = 3; diff --git a/test/src/common.js b/test/src/common.js new file mode 100644 index 0000000..c7b6a1f --- /dev/null +++ b/test/src/common.js @@ -0,0 +1,3 @@ +exports.tragedy = function tragedy() { + return 'common'; +}; diff --git a/test/src/index.test.js b/test/src/index.test.js index 0b1bfc8..35d201b 100644 --- a/test/src/index.test.js +++ b/test/src/index.test.js @@ -8,6 +8,7 @@ describe('worker', () => { it('should be an instance of Worker', () => { worker = new Worker(); + // eslint-disable-next-line jest/no-jasmine-globals expect(worker).toEqual(jasmine.any(window.Worker)); }); @@ -15,6 +16,25 @@ describe('worker', () => { expect(await worker.foo()).toBe(1); }); + it('worker.otherFoo()', async () => { + expect(await worker.otherFoo()).toBe(-1); + }); + + it('worker.otherOtherFoo()', async () => { + expect(await worker.otherOtherFoo()).toBe(2); + }); + it('worker.andTheOtherFoo()', async () => { + expect(await worker.andTheOtherFoo()).toBe(2); + }); + + it('worker.anyFoo()', async () => { + expect(await worker.anyFoo()).toBe(4); + }); + + it('worker.tragedy()', async () => { + expect(await worker.tragedy()).toBe('common'); + }); + it('worker.bar()', async () => { let out = await worker.bar('a', 'b'); expect(out).toEqual('a [bar:3] b'); @@ -102,6 +122,7 @@ describe('?import option', () => { it('should be an instance of Worker', () => { worker = new ImportWorker(); + // eslint-disable-next-line jest/no-jasmine-globals expect(worker).toEqual(jasmine.any(window.Worker)); }); diff --git a/test/src/other.js b/test/src/other.js index f4fbc35..8a2402b 100644 --- a/test/src/other.js +++ b/test/src/other.js @@ -1,3 +1,5 @@ -export function otherFoo() {} +export function otherFoo() { + return -1; +} -export const otherBar = 3; \ No newline at end of file +export const otherBar = 3; diff --git a/test/src/worker.js b/test/src/worker.js index 73b1049..1751c3c 100644 --- a/test/src/worker.js +++ b/test/src/worker.js @@ -1,11 +1,17 @@ import { otherFoo, otherBar } from './other'; export { otherFoo }; +export { otherOtherFoo as andTheOtherFoo } from './and-the-other'; +export * from './and-the-other'; + +export { tragedy } from './common.js'; export function foo() { return 1; } +export const value = 3; + export function throwError() { throw new Error('Error in worker.js'); } From 0d19fc7e0d00f2ea27dd5593d8769ed63f793d28 Mon Sep 17 00:00:00 2001 From: Kevin Decker Date: Sun, 21 Jun 2020 10:23:20 -0500 Subject: [PATCH 2/3] Remove parser in favor of providedExports --- src/index.js | 74 +++++----------------------------------------------- 1 file changed, 7 insertions(+), 67 deletions(-) diff --git a/src/index.js b/src/index.js index 01b019d..7c0cb24 100644 --- a/src/index.js +++ b/src/index.js @@ -7,30 +7,6 @@ import WebWorkerTemplatePlugin from 'webpack/lib/webworker/WebWorkerTemplatePlug export default function loader() {} -const CACHE = {}; -const tapName = 'workerize-loader'; - -function compilationHook(compiler, handler) { - if (compiler.hooks) { - return compiler.hooks.compilation.tap(tapName, handler); - } - return compiler.plugin('compilation', handler); -} - -function parseHook(data, handler) { - if (data.normalModuleFactory.hooks) { - return data.normalModuleFactory.hooks.parser.for('javascript/auto').tap(tapName, handler); - } - return data.normalModuleFactory.plugin('parser', handler); -} - -function exportDeclarationHook(parser, handler) { - if (parser.hooks) { - return parser.hooks.exportDeclaration.tap(tapName, handler); - } - return parser.plugin('export declaration', handler); -} - loader.pitch = function(request) { this.cacheable(false); @@ -84,56 +60,20 @@ loader.pitch = function(request) { } (new SingleEntryPlugin(this.context, `!!${path.resolve(__dirname, 'rpc-worker-loader.js')}!${request}`, 'main')).apply(worker.compiler); - - const subCache = `subcache ${__dirname} ${request}`; - - compilationHook(worker.compiler, (compilation, data) => { - if (compilation.cache) { - if (!compilation.cache[subCache]) compilation.cache[subCache] = {}; - - compilation.cache = compilation.cache[subCache]; - } - parseHook(data, (parser, options) => { - exportDeclarationHook(parser, expr => { - let decl = expr.declaration || expr, - { compilation, current } = parser.state, - entry = compilation.entries[0].resource; - - // only process entry exports - if (current.resource!==entry) return; - - let key = current.nameForCondition(); - let exports = CACHE[key] || (CACHE[key] = {}); - - if (decl.id) { - exports[decl.id.name] = true; - } - else if (decl.declarations) { - for (let i=0; i { if (err) return cb(err); if (entries[0]) { worker.file = entries[0].files[0]; - let key = entries[0].entryModule.nameForCondition(); let contents = compilation.assets[worker.file].source(); - let exports = Array.from( - new Set([ - ...Object.keys(CACHE[key] || {}), - ...entries[0].entryModule.buildMeta.providedExports - ]) - ); + + if (entries[0].entryModule.buildMeta.providedExports === true) { + // Can also occur if doing `export * from 'common js module'` + throw new Error('Attempted to load a worker implemented in CommonJS'); + } + + let exports = entries[0].entryModule.buildMeta.providedExports; // console.log('Workerized exports: ', exports.join(', ')); From efe68c800121e7a584a9c6092adecfae97b260d8 Mon Sep 17 00:00:00 2001 From: Kevin Decker Date: Sun, 21 Jun 2020 10:23:41 -0500 Subject: [PATCH 3/3] Update file lookup to work in webpack 5 --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 7c0cb24..68092ba 100644 --- a/src/index.js +++ b/src/index.js @@ -64,7 +64,7 @@ loader.pitch = function(request) { if (err) return cb(err); if (entries[0]) { - worker.file = entries[0].files[0]; + worker.file = Array.from(entries[0].files)[0]; let contents = compilation.assets[worker.file].source();