diff --git a/package-lock.json b/package-lock.json index 3876535..0bf0675 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@exact-realty/esbuild-plugin-closure-compiler", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@exact-realty/esbuild-plugin-closure-compiler", - "version": "1.0.0", + "version": "1.0.1", "license": "Apache-2.0 WITH LLVM-exception", "devDependencies": { "@types/google-closure-compiler": "^0.0.21", diff --git a/package.json b/package.json index 4fc5479..4eeadb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@exact-realty/esbuild-plugin-closure-compiler", - "version": "1.0.0", + "version": "1.0.1", "description": "esbuild plugin for compiling with Google Closure Compiler as the last step", "main": "./dist/index.cjs", "module": "./dist/index.mjs", diff --git a/src/esmDynamicImports.ts b/src/esmDynamicImports.ts index d16de9b..ba86721 100644 --- a/src/esmDynamicImports.ts +++ b/src/esmDynamicImports.ts @@ -19,7 +19,7 @@ const dymamicImportExpressionRegex = const preprocess = (text: string): string => text.replace( dymamicImportExpressionRegex, - 'globalThis.__reserved__["%dymamic_import%"]', + 'globalThis["__reserved__"]["%dymamic_import%"]', ); const postprocess = (text: string): string => { diff --git a/src/esmExports.ts b/src/esmExports.ts index ba4e6a4..8c7adfb 100644 --- a/src/esmExports.ts +++ b/src/esmExports.ts @@ -17,14 +17,14 @@ const preprocess = (text: string): string => text .replace( /export\s+default\b/g, - '/** @nocollapse */globalThis.__reserved__["%export"]["default"]=', + '/** @nocollapse */globalThis["__reserved__"]["%export"]["default"]=', ) .replace(/export\s*{([^}]+)}/g, (_, p1: string) => { return p1 .split(',') .map( (e) => - '/** @nocollapse */globalThis.__reserved__["%export"]' + + '/** @nocollapse */globalThis["__reserved__"]["%export"]' + (/\sas\s/.test(e) ? e.replace(/(.+)\sas\s(.+)/, (_, p1, p2) => { return `[${JSON.stringify( diff --git a/src/esmImports.ts b/src/esmImports.ts index 4e0b877..142e24a 100644 --- a/src/esmImports.ts +++ b/src/esmImports.ts @@ -22,7 +22,7 @@ const preprocess = (text: string): string => importExpressionRegex, (_, defaultExport, starName, namedImports, from, moduleName) => { return ( - '/** @nocollapse */ globalThis.__reserved__["%import_start"]();' + + '/** @nocollapse */ globalThis["__reserved__"]["%import_start"]();' + `${ from ? `const {${[ @@ -35,8 +35,8 @@ const preprocess = (text: string): string => .filter(Boolean) .join(',')}}=` : '' - }globalThis.__reserved__["%import"](${moduleName});` + - '/** @nocollapse */ globalThis.__reserved__["%import_end"]()' + }globalThis["__reserved__"]["%import"](${moduleName});` + + '/** @nocollapse */ globalThis["__reserved__"]["%import_end"]()' ); }, ) @@ -45,7 +45,7 @@ const preprocess = (text: string): string => .split(',') .map( (e) => - '/** @nocollapse */globalThis.__reserved__["%export"]' + + '/** @nocollapse */globalThis["__reserved__"]["%export"]' + (/\sas\s/.test(e) ? e.replace(/(.+)\sas\s(.+)/, (_, p1, p2) => { return `[${JSON.stringify( diff --git a/src/getCompiler.ts b/src/getCompiler.ts index 8813a21..1b0d73f 100644 --- a/src/getCompiler.ts +++ b/src/getCompiler.ts @@ -15,14 +15,22 @@ import type esbuild from 'esbuild'; import googleClosureCompiler from 'google-closure-compiler'; +import * as esmDynamicImports from './esmDynamicImports.js'; import * as esmExports from './esmExports.js'; import * as esmImports from './esmImports.js'; -import * as esmDynamicImports from './esmDynamicImports.js'; import * as umdExports from './umdExports.js'; +/* The following functions ensure that external code can include __reserved__ + in it, without causing interference with the preprocessing and postprocessing + functions + */ +const preprocessReserved = (x: string) => x.replace(/(__reserved__)/g, '_$1_'); +const postprocessReserved = (x: string) => x.replace(/_(__reserved__)_/g, '$1'); + const esm = { preprocess: (x: string): string => { return [ + preprocessReserved, esmDynamicImports.preprocess, esmExports.preprocess, esmImports.preprocess, @@ -33,22 +41,25 @@ const esm = { esmDynamicImports.postprocess, esmExports.postprocess, esmImports.postprocess, + postprocessReserved, ].reduce((acc, cv) => cv(acc), x); }, }; const umd = { preprocess: (x: string): string => { - return [esmDynamicImports.preprocess, umdExports.preprocess].reduce( - (acc, cv) => cv(acc), - x, - ); + return [ + preprocessReserved, + esmDynamicImports.preprocess, + umdExports.preprocess, + ].reduce((acc, cv) => cv(acc), x); }, postprocess: (x: string): string => { - return [esmDynamicImports.postprocess, umdExports.postprocess].reduce( - (acc, cv) => cv(acc), - x, - ); + return [ + esmDynamicImports.postprocess, + umdExports.postprocess, + postprocessReserved, + ].reduce((acc, cv) => cv(acc), x); }, }; @@ -60,34 +71,39 @@ const getCompiler = ( const buildModule = esmOutput ? esm : umd; - const compiler = new googleClosureCompiler.compiler({ - language_in: 'ECMASCRIPT_2020', - language_out: 'ECMASCRIPT_2015', - env: 'BROWSER', - ...compilerOptions, - rewrite_polyfills: false, - process_closure_primitives: false, - apply_input_source_maps: false, - warning_level: 'QUIET', - isolate_polyfills: true, - assume_function_wrapper: esmOutput, - }); + // A new instance is needed every time because of how the command lines + // are constructed + const compilerFactory = () => + new googleClosureCompiler.compiler({ + language_in: 'ECMASCRIPT_2020', + language_out: 'ECMASCRIPT_2015', + env: 'BROWSER', + ...compilerOptions, + rewrite_polyfills: false, + process_closure_primitives: false, + apply_input_source_maps: false, + warning_level: 'QUIET', + isolate_polyfills: true, + assume_function_wrapper: esmOutput, + }); return (text: string) => { text = buildModule.preprocess(text); return new Promise((resolve, reject) => { - const process = compiler.run((exitCode, stdout, stderr) => { - if (exitCode === 0) { - // TODO: Warnings - stdout = buildModule.postprocess(stdout); + const process = compilerFactory().run( + (exitCode, stdout, stderr) => { + if (exitCode === 0) { + // TODO: Warnings + stdout = buildModule.postprocess(stdout); - resolve(stdout); - } else { - // TODO: Better error handing - return reject(new Error(stderr)); - } - }); + resolve(stdout); + } else { + // TODO: Better error handing + return reject(new Error(stderr)); + } + }, + ); if (!process.stdin) { process.kill();