diff --git a/packages/core/integration-tests/package.json b/packages/core/integration-tests/package.json index 4d1a17247cf..fc883990c14 100644 --- a/packages/core/integration-tests/package.json +++ b/packages/core/integration-tests/package.json @@ -29,6 +29,7 @@ "cross-env": "^7.0.0", "elm": "^0.19.1-5", "elm-hot": "^1.1.5", + "esbuild-register": "^3.5.0", "exif-reader": "^1.0.3", "get-port": "^5.0.0", "graphql": "^15.0.0", diff --git a/packages/core/integration-tests/test/registered-plugins.js b/packages/core/integration-tests/test/registered-plugins.js new file mode 100644 index 00000000000..e3ba7c91b4b --- /dev/null +++ b/packages/core/integration-tests/test/registered-plugins.js @@ -0,0 +1,69 @@ +// @flow strict-local +import assert from 'assert'; +import path from 'path'; +import {bundle, run, overlayFS, fsFixture} from '@parcel/test-utils'; + +describe('plugins with "registered" languages', () => { + it('should support plugins with esbuild-register', async () => { + const dir = path.join(__dirname, 'esbuild-register-plugin'); + overlayFS.mkdirp(dir); + + await fsFixture(overlayFS, dir)` + package.json: + { + "name": "app", + "sideEffects": true + } + + yarn.lock: + + index.js: + console.log("Hi, mum!"); + + .parcelrc: + { + extends: "@parcel/config-default", + reporters: ["...", "./reporter-plugin.js"], + } + + reporter-plugin.js: + require('esbuild-register/dist/node').register(); + const plugin = require('./reporter-plugin.ts'); + module.exports = plugin; + + reporter-plugin.ts: + import fs from 'fs'; + import { Reporter } from '@parcel/plugin'; + import { someString } from './some-string'; + export default new Reporter({ + async report({ event, options }) { + if (event.type === 'buildStart') { + await options.outputFS.writeFile(options.projectRoot + '/output.txt', 'Hello! ' + someString, 'utf8'); + } + } + }); + + some-string.ts: + export const someString = 'something'; + `; + + const b = await bundle(path.join(dir, 'index.js'), { + inputFS: overlayFS, + outputFS: overlayFS, + additionalReporters: [ + {packageName: '@parcel/reporter-json', resolveFrom: __filename}, + ], + }); + + await run(b); + + // Tests that the plugin actually loaded properly by validating that it output + // what it was supposed to output. If `esbuild-register` isn't used, or the resolver + // doesn't support updating extensions as they change, then the plugin won't work. + assert(overlayFS.existsSync(path.join(dir, 'output.txt'))); + assert.equal( + overlayFS.readFileSync(path.join(dir, 'output.txt'), 'utf8'), + 'Hello! something', + ); + }); +}); diff --git a/packages/core/package-manager/src/NodePackageManager.js b/packages/core/package-manager/src/NodePackageManager.js index 31d1268cfea..dc1d091f871 100644 --- a/packages/core/package-manager/src/NodePackageManager.js +++ b/packages/core/package-manager/src/NodePackageManager.js @@ -58,6 +58,7 @@ export class NodePackageManager implements PackageManager { projectRoot: FilePath; installer: ?PackageInstaller; resolver: ResolverBase; + currentExtensions: Array; constructor( fs: FileSystem, @@ -67,6 +68,11 @@ export class NodePackageManager implements PackageManager { this.fs = fs; this.projectRoot = projectRoot; this.installer = installer; + + // $FlowFixMe - no type for _extensions + this.currentExtensions = Object.keys(Module._extensions).map(e => + e.substring(1), + ); } _createResolver(): ResolverBase { @@ -96,6 +102,7 @@ export class NodePackageManager implements PackageManager { ); } : undefined, + extensions: this.currentExtensions, }); } @@ -170,6 +177,17 @@ export class NodePackageManager implements PackageManager { // $FlowFixMe let m = new Module(filePath, Module._cache[from] || module.parent); + + // $FlowFixMe _extensions not in type + const extensions = Object.keys(Module._extensions); + // This handles supported extensions changing due to, for example, esbuild/register being used + // We assume that the extension list will change in size - as these tools usually add support for + // additional extensions. + if (extensions.length !== this.currentExtensions.length) { + this.currentExtensions = extensions.map(e => e.substring(1)); + this.resolver = this._createResolver(); + } + // $FlowFixMe[prop-missing] Module._cache[filePath] = m; diff --git a/yarn.lock b/yarn.lock index 3f88dc646fd..eff31a9dfde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4955,6 +4955,13 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.4: + version "4.3.4" + resolved "https://packages.atlassian.com/api/npm/npm-remote/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -5662,6 +5669,13 @@ esbuild-openbsd-64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.12.tgz#adde32f2f1b05dc4bd4fc544d6ea5a4379f9ca4d" integrity sha512-KuLCmYMb2kh05QuPJ+va60bKIH5wHL8ypDkmpy47lzwmdxNsuySeCMHuTv5o2Af1RUn5KLO5ZxaZeq4GEY7DaQ== +esbuild-register@^3.5.0: + version "3.5.0" + resolved "https://packages.atlassian.com/api/npm/npm-remote/esbuild-register/-/esbuild-register-3.5.0.tgz#449613fb29ab94325c722f560f800dd946dc8ea8" + integrity sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A== + dependencies: + debug "^4.3.4" + esbuild-sunos-64@0.13.12: version "0.13.12" resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.12.tgz#a7ecaf52b7364fbee76dc8aa707fa3e1cff3342c"