UNPKG

use-macro

Version:

ESBuild plugin that allows you to execute functions at compile time and inline the output

182 lines 16.1 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { runInNewContext } from 'vm'; import * as ts from 'typescript'; import { dirname } from 'path'; import { createRequire } from 'module'; import { parse } from '@babel/parser'; import _traverse from '@babel/traverse'; import * as t from '@babel/types'; import _generate from '@babel/generator'; import { stringify } from './stringify.js'; const traverse = _traverse.default; const generate = _generate.default; // Helper to get parser options based on file extension const getParserOptions = (filepath) => { const isTS = /\.tsx?$/.test(filepath); const isJSX = /\.jsx$/.test(filepath) || /\.tsx$/.test(filepath); const isModule = /^m/.test(filepath); return { sourceType: isModule ? 'module' : 'unambiguous', plugins: [ ...(isTS ? ['typescript'] : []), ...(isJSX ? ['jsx'] : []), 'decorators-legacy', 'classProperties', 'optionalChaining', 'nullishCoalescingOperator', ], }; }; // Helper to transpile TypeScript to JavaScript const transpileTypeScript = (code, filePath) => { const result = ts.transpileModule(code, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ESNext, }, fileName: filePath, }); return result.outputText; }; // Helper to execute macro at compile time const executeMacro = (macroFunction) => { var _a, _b; const macroCode = generate(macroFunction.ast).code; const transpiledCode = /\.(m|c|d)?tsx?$/.test(macroFunction.path) ? transpileTypeScript(macroCode, macroFunction.path) : macroCode; const macroModule = ` ${transpiledCode} // do not export this as it is evaluated in vm which directly returns the result ${(_a = macroFunction.ast.id) === null || _a === void 0 ? void 0 : _a.name}(${macroFunction.args.join(', ')})`; const result = runInNewContext(`${macroModule}`, Object.assign(Object.assign({}, Object.fromEntries(Object.entries(globalThis))), { process, Buffer, URL, URLSearchParams, fetch, Response, Headers, Request, FormData, console, setTimeout, clearTimeout, setInterval, clearInterval, setImmediate, AbortController, AbortSignal, __dirname: dirname(macroFunction.path), __filename: macroFunction.path, require: createRequire(macroFunction.path), import: (modulePath) => import(modulePath), isMacroContext: true })); return (_b = result === null || result === void 0 ? void 0 : result.default) !== null && _b !== void 0 ? _b : result; }; export class MacroTransformer { constructor() { this.cache = new Map(); this.functions = new Map(); } transform(contents, filePath) { return __awaiter(this, void 0, void 0, function* () { const macroFunctions = this.functions; const macroCache = this.cache; const ast = parse(contents, getParserOptions(filePath)); const state = { modifications: [], macrosToRemove: new Set(), macrosToExecute: [], }; const runMacro = (name, fn) => __awaiter(this, void 0, void 0, function* () { if (macroCache.has(name)) { return macroCache.get(name); } const result = yield executeMacro(fn); const stringifiedResult = yield stringify(result); macroCache.set(name, stringifiedResult); return stringifiedResult; }); traverse(ast, { 'FunctionDeclaration|FunctionExpression|ArrowFunctionExpression'(path) { var _a, _b; const node = path.node; if (!t.isFunction(node)) return; const body = node.body; if (!t.isBlockStatement(body)) return; if (body.directives) { const directive = body.directives.find((d) => d.value.value === 'use macro'); if (directive) { let functionName; if (t.isFunctionDeclaration(node) && node.id) { functionName = node.id.name; } else if (path.parent && t.isVariableDeclarator(path.parent) && t.isIdentifier(path.parent.id)) { functionName = path.parent.id.name; } if (!functionName) { const err = new Error(`Macro function at at ${filePath}:${(_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line}:${(_b = node.loc) === null || _b === void 0 ? void 0 : _b.start.column} must have a name. If you are using an IIFE, it is not supported.`); throw err; } const macroFunction = { ast: t.isFunctionDeclaration(node) ? node : t.functionDeclaration(t.identifier(functionName), // @ts-ignore node.params, body), path: filePath, args: node.params, }; macroFunctions.set(functionName, macroFunction); // Add to removal queue const nodeToRemove = t.isFunctionDeclaration(node) ? path : path.parentPath; if (nodeToRemove) { state.macrosToRemove.add(nodeToRemove); } } } }, CallExpression(path) { if (t.isIdentifier(path.node.callee)) { const functionName = path.node.callee.name; const fn = macroFunctions.get(functionName); if (!fn) return; state.modifications.push(() => __awaiter(this, void 0, void 0, function* () { const value = yield runMacro(functionName, fn); const newNode = t.identifier(value); t.addComment(newNode, 'leading', ` @__MACRO__ ${functionName} `); path.replaceWith(newNode); })); } }, }); // Apply all modifications in a single pass for (const modify of state.modifications) { yield modify(); } // Remove all macro definitions state.macrosToRemove.forEach((path) => path.remove()); const { code } = generate(ast, { retainLines: true, compact: false, sourceMaps: true, sourceFileName: filePath, }); return { contents: code, loader: filePath.split('.').pop(), }; }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNmb3JtZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLElBQUksQ0FBQztBQUNyQyxPQUFPLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNqQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFdkMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0QyxPQUFPLFNBQVMsTUFBTSxpQkFBaUIsQ0FBQztBQUN4QyxPQUFPLEtBQUssQ0FBQyxNQUFNLGNBQWMsQ0FBQztBQUNsQyxPQUFPLFNBQVMsTUFBTSxrQkFBa0IsQ0FBQztBQUd6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFVM0MsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQztBQUNuQyxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDO0FBRW5DLHVEQUF1RDtBQUN2RCxNQUFNLGdCQUFnQixHQUFHLENBQUMsUUFBZ0IsRUFBRSxFQUFFO0lBQzVDLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFckMsT0FBTztRQUNMLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsYUFBYTtRQUMvQyxPQUFPLEVBQUU7WUFDUCxH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