diff --git a/src/index.js b/src/index.js index acc864b..d590c67 100644 --- a/src/index.js +++ b/src/index.js @@ -23,7 +23,7 @@ const comlinkLoaderSpecificOptions = [ 'singleton' ]; -export default function loader () { } +export default function loader() { } loader.pitch = function (request) { const options = loaderUtils.getOptions(this) || {}; @@ -39,30 +39,56 @@ loader.pitch = function (request) { const remainingRequest = JSON.stringify(workerLoader + '!' + request); + const wrapperBuilder = ` + var Worker = require(${remainingRequest}); + var wrap = require('comlink').wrap; + + function getWrappedWorker() { + var worker = Worker(); + var wrapper = wrap(worker); + + if (typeof Proxy === 'function') { + var proxy = new Proxy(wrapper, { + get: function (target, prop, receiver) { + if (prop === 'worker') { + return worker; + } + return Reflect.get(...arguments); + } + }); + + return proxy; + } else { + wrapper.worker = worker; + return wrapper; + } + } `; + + // ?singleton mode: export an instance of the worker if (singleton === true) { return ` - module.exports = require('comlink').wrap(require(${remainingRequest})()); - ${options.module === false ? '' : 'module.exports.__esModule = true;'} - `.replace(/\n\s*/g, ''); + ${wrapperBuilder} + module.exports = getWrappedWorker(); + ${ options.module === false ? '' : 'module.exports.__esModule = true;'} + `.replace(/\n\s*/g, ''); } // ?singleton=false mode: always return a new worker from the factory if (singleton === false) { return ` - module.exports = function () { - return require('comlink').wrap(require(${remainingRequest})()); - }; - `.replace(/\n\s*/g, ''); + ${wrapperBuilder} + module.exports = getWrappedWorker; `.replace(/\n\s*/g, ''); } return ` - var wrap = require('comlink').wrap, - Worker = require(${remainingRequest}), - inst; - module.exports = function f() { - if (this instanceof f) return wrap(Worker()); - return inst || (inst = wrap(Worker())); - }; + ${ wrapperBuilder} + var inst; + module.exports = function f() { + if (this instanceof f) + return getWrappedWorker(); + + return inst || (inst = getWrappedWorker()); + }; `.replace(/\n\s*/g, ''); }; diff --git a/test/index.test.js b/test/index.test.js index 5ebb62b..e33fda1 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -18,12 +18,20 @@ import sinon from 'sinon'; import 'jasmine-sinon'; import MyWorker from 'comlink-loader!./worker'; -const OriginalWorker = self.Worker; -self.Worker = sinon.spy((url, opts) => new OriginalWorker(url, opts)); - describe('worker', () => { + let OriginalWorker; let worker, inst; + beforeAll(() => { + OriginalWorker = self.Worker; + self.Worker = sinon.spy((url, opts) => new OriginalWorker(url, opts)); + }); + + afterAll(() => { + // Reset the original Worker constructor for next tests + self.Worker = OriginalWorker; + }); + it('should be a factory', async () => { worker = new MyWorker(); expect(self.Worker).toHaveBeenCalledOnce(); @@ -74,4 +82,12 @@ describe('worker', () => { expect(self.Worker).not.toHaveBeenCalled(); }); + + it('should have a property to access the underlying worker', async () => { + self.Worker.resetHistory(); + + const worker = MyWorker(); + expect(worker.worker instanceof OriginalWorker).toBe(true); + }); }); + diff --git a/test/singleton.test.js b/test/singleton.test.js index 4dc8213..66ffc62 100644 --- a/test/singleton.test.js +++ b/test/singleton.test.js @@ -17,12 +17,20 @@ import sinon from 'sinon'; import 'jasmine-sinon'; -const OriginalWorker = self.Worker; -self.Worker = sinon.spy((url, opts) => new OriginalWorker(url, opts)); - describe('singleton', () => { + let OriginalWorker; let exported; + beforeAll(() => { + OriginalWorker = self.Worker; + self.Worker = sinon.spy((url, opts) => new OriginalWorker(url, opts)); + }); + + afterAll(() => { + // Reset the original Worker constructor for next tests + self.Worker = OriginalWorker; + }); + it('should immediately instantiate the worker', async () => { // we're using dynamic import here so the Worker spy can be installed before-hand exported = require('comlink-loader?singleton!./worker'); @@ -50,4 +58,9 @@ describe('singleton', () => { expect(e).toMatch(/Error/); } }); + + it('should have a property to access the underlying worker', async () => { + expect(exported.worker instanceof OriginalWorker).toBe(true); + }); }); +