summaryrefslogtreecommitdiff
path: root/node_modules/@esbuild-plugins/node-modules-polyfill/src/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@esbuild-plugins/node-modules-polyfill/src/index.ts')
-rw-r--r--node_modules/@esbuild-plugins/node-modules-polyfill/src/index.ts133
1 files changed, 133 insertions, 0 deletions
diff --git a/node_modules/@esbuild-plugins/node-modules-polyfill/src/index.ts b/node_modules/@esbuild-plugins/node-modules-polyfill/src/index.ts
new file mode 100644
index 0000000..f7397e4
--- /dev/null
+++ b/node_modules/@esbuild-plugins/node-modules-polyfill/src/index.ts
@@ -0,0 +1,133 @@
+import { OnResolveArgs, Plugin } from 'esbuild'
+import escapeStringRegexp from 'escape-string-regexp'
+import fs from 'fs'
+import path from 'path'
+import esbuild from 'esbuild'
+import { builtinsPolyfills } from './polyfills'
+
+// import { NodeResolvePlugin } from '@esbuild-plugins/node-resolve'
+const NAME = 'node-modules-polyfills'
+const NAMESPACE = NAME
+
+function removeEndingSlash(importee) {
+ if (importee && importee.slice(-1) === '/') {
+ importee = importee.slice(0, -1)
+ }
+ return importee
+}
+
+export interface NodePolyfillsOptions {
+ name?: string
+ namespace?: string
+}
+
+export function NodeModulesPolyfillPlugin(
+ options: NodePolyfillsOptions = {},
+): Plugin {
+ const { namespace = NAMESPACE, name = NAME } = options
+ if (namespace.endsWith('commonjs')) {
+ throw new Error(`namespace ${namespace} must not end with commonjs`)
+ }
+ // this namespace is needed to make ES modules expose their default export to require: require('assert') will give you import('assert').default
+ const commonjsNamespace = namespace + '-commonjs'
+ const polyfilledBuiltins = builtinsPolyfills()
+ const polyfilledBuiltinsNames = [...polyfilledBuiltins.keys()]
+
+ return {
+ name,
+ setup: function setup({ onLoad, onResolve, initialOptions }) {
+ // polyfills contain global keyword, it must be defined
+ if (initialOptions?.define && !initialOptions.define?.global) {
+ initialOptions.define['global'] = 'globalThis'
+ } else if (!initialOptions?.define) {
+ initialOptions.define = { global: 'globalThis' }
+ }
+
+ // TODO these polyfill module cannot import anything, is that ok?
+ async function loader(
+ args: esbuild.OnLoadArgs,
+ ): Promise<esbuild.OnLoadResult> {
+ try {
+ const argsPath = args.path.replace(/^node:/, '')
+ const isCommonjs = args.namespace.endsWith('commonjs')
+
+ const resolved = polyfilledBuiltins.get(
+ removeEndingSlash(argsPath),
+ )
+ const contents = await (
+ await fs.promises.readFile(resolved)
+ ).toString()
+ let resolveDir = path.dirname(resolved)
+
+ if (isCommonjs) {
+ return {
+ loader: 'js',
+ contents: commonJsTemplate({
+ importPath: argsPath,
+ }),
+ resolveDir,
+ }
+ }
+ return {
+ loader: 'js',
+ contents,
+ resolveDir,
+ }
+ } catch (e) {
+ console.error('node-modules-polyfill', e)
+ return {
+ contents: `export {}`,
+ loader: 'js',
+ }
+ }
+ }
+ onLoad({ filter: /.*/, namespace }, loader)
+ onLoad({ filter: /.*/, namespace: commonjsNamespace }, loader)
+ const filter = new RegExp(
+ [
+ ...polyfilledBuiltinsNames,
+ ...polyfilledBuiltinsNames.map((n) => `node:${n}`),
+ ]
+ .map(escapeStringRegexp)
+ .join('|'), // TODO builtins could end with slash, keep in mind in regex
+ )
+ async function resolver(args: OnResolveArgs) {
+ const argsPath = args.path.replace(/^node:/, '')
+ const ignoreRequire = args.namespace === commonjsNamespace
+
+ if (!polyfilledBuiltins.has(argsPath)) {
+ return
+ }
+
+ const isCommonjs =
+ !ignoreRequire && args.kind === 'require-call'
+
+ return {
+ namespace: isCommonjs ? commonjsNamespace : namespace,
+ path: argsPath,
+ }
+ }
+ onResolve({ filter }, resolver)
+ // onResolve({ filter: /.*/, namespace }, resolver)
+ },
+ }
+}
+
+function commonJsTemplate({ importPath }) {
+ return `
+const polyfill = require('${importPath}')
+
+if (polyfill && polyfill.default) {
+ module.exports = polyfill.default
+ for (let k in polyfill) {
+ module.exports[k] = polyfill[k]
+ }
+} else if (polyfill) {
+ module.exports = polyfill
+}
+
+
+`
+}
+
+export default NodeModulesPolyfillPlugin