@farm.js/react 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vite.mjs ADDED
@@ -0,0 +1,571 @@
1
+ import { normalizePath } from 'vite';
2
+ import { transformAsync, types, traverse } from '@babel/core';
3
+
4
+ // src/vite.ts
5
+ function isComponentName(name) {
6
+ return /^[A-Z]/.test(name);
7
+ }
8
+ function directiveValues(node) {
9
+ return (node.directives || []).map((directive) => directive.value.value);
10
+ }
11
+ function isUseStateCall(expression, useStateNames, reactNames) {
12
+ if (!types.isCallExpression(expression)) return false;
13
+ if (types.isIdentifier(expression.callee)) return useStateNames.has(expression.callee.name);
14
+ return types.isMemberExpression(expression.callee) && !expression.callee.computed && types.isIdentifier(expression.callee.object) && reactNames.has(expression.callee.object.name) && types.isIdentifier(expression.callee.property, { name: "useState" });
15
+ }
16
+ function cloneExpression(expression) {
17
+ return types.cloneNode(expression, true);
18
+ }
19
+ function expressionFile(expression) {
20
+ return types.file(types.program([types.expressionStatement(expression)]));
21
+ }
22
+ function collectStateDependencies(expression, statesByValue) {
23
+ const dependencies = /* @__PURE__ */ new Set();
24
+ const file = expressionFile(cloneExpression(expression));
25
+ traverse(file, {
26
+ ReferencedIdentifier(path) {
27
+ const state = statesByValue.get(path.node.name);
28
+ if (state && !path.scope.hasBinding(path.node.name)) dependencies.add(state.index);
29
+ }
30
+ });
31
+ return [...dependencies].sort((left, right) => left - right);
32
+ }
33
+ function referencesIdentifier(expression, name) {
34
+ let referenced = false;
35
+ traverse(expressionFile(cloneExpression(expression)), {
36
+ ReferencedIdentifier(path) {
37
+ if (path.node.name === name && !path.scope.hasBinding(name)) {
38
+ referenced = true;
39
+ }
40
+ }
41
+ });
42
+ return referenced;
43
+ }
44
+ function findContainingEvent(path) {
45
+ const attribute = path.findParent((parent) => parent.isJSXAttribute());
46
+ if (!attribute?.isJSXAttribute() || !types.isJSXIdentifier(attribute.node.name)) return null;
47
+ return /^on[A-Z]/.test(attribute.node.name.name) ? attribute : null;
48
+ }
49
+ function validateSetterUsage(root, statesBySetter) {
50
+ const file = expressionFile(types.cloneNode(root, true));
51
+ let reason;
52
+ traverse(file, {
53
+ ReferencedIdentifier(path) {
54
+ if (reason) return;
55
+ const state = statesBySetter.get(path.node.name);
56
+ if (!state || path.scope.hasBinding(path.node.name)) return;
57
+ const parent = path.parentPath;
58
+ if (!parent.isCallExpression() || parent.node.callee !== path.node || !findContainingEvent(parent)) {
59
+ reason = `${state.setterName} must be called inside a JSX event handler`;
60
+ }
61
+ }
62
+ });
63
+ return reason;
64
+ }
65
+ function rewriteStateAccess(expression, stateParameter, statesByValue, statesBySetter) {
66
+ const file = expressionFile(cloneExpression(expression));
67
+ traverse(file, {
68
+ CallExpression(path) {
69
+ const callee = path.get("callee");
70
+ if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
71
+ const state = statesBySetter.get(callee.node.name);
72
+ if (!state) return;
73
+ callee.replaceWith(
74
+ types.memberExpression(
75
+ types.memberExpression(types.cloneNode(stateParameter), types.numericLiteral(state.index), true),
76
+ types.identifier("set")
77
+ )
78
+ );
79
+ },
80
+ ReferencedIdentifier(path) {
81
+ const state = statesByValue.get(path.node.name);
82
+ if (!state || path.scope.hasBinding(path.node.name)) return;
83
+ path.replaceWith(
84
+ types.callExpression(
85
+ types.memberExpression(
86
+ types.memberExpression(types.cloneNode(stateParameter), types.numericLiteral(state.index), true),
87
+ types.identifier("get")
88
+ ),
89
+ []
90
+ )
91
+ );
92
+ }
93
+ });
94
+ return file.program.body[0].expression;
95
+ }
96
+ function cleanJsxText(value) {
97
+ const lines = value.replace(/\r/g, "").split("\n");
98
+ let result = "";
99
+ for (let index = 0; index < lines.length; index += 1) {
100
+ const lastNonEmptyLine = lines.slice(index + 1).every((line2) => line2.trim().length === 0);
101
+ let line = lines[index].replace(/\t/g, " ").replace(/ +/g, " ");
102
+ if (index > 0) line = line.replace(/^ /, "");
103
+ if (!lastNonEmptyLine) line = line.replace(/ $/, "");
104
+ if (line) result += line + (!lastNonEmptyLine ? " " : "");
105
+ }
106
+ return result;
107
+ }
108
+ function isTextExpression(expression) {
109
+ let supported = true;
110
+ traverse(expressionFile(cloneExpression(expression)), {
111
+ CallExpression(path) {
112
+ supported = false;
113
+ path.stop();
114
+ },
115
+ OptionalCallExpression(path) {
116
+ supported = false;
117
+ path.stop();
118
+ },
119
+ JSXElement(path) {
120
+ supported = false;
121
+ path.stop();
122
+ },
123
+ JSXFragment(path) {
124
+ supported = false;
125
+ path.stop();
126
+ },
127
+ ObjectExpression(path) {
128
+ supported = false;
129
+ path.stop();
130
+ },
131
+ Function(path) {
132
+ supported = false;
133
+ path.stop();
134
+ }
135
+ });
136
+ return supported;
137
+ }
138
+ function jsxAttributeName(attribute) {
139
+ return types.isJSXIdentifier(attribute.name) ? attribute.name.name : void 0;
140
+ }
141
+ function analyzeHostTree(root, statesByValue) {
142
+ const bindings = [];
143
+ const visit = (element, path) => {
144
+ const tag = element.openingElement.name;
145
+ if (!types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
146
+ return "compiled trees currently support host elements only";
147
+ }
148
+ for (const attribute of element.openingElement.attributes) {
149
+ if (types.isJSXSpreadAttribute(attribute)) return "JSX attribute spreads are not supported yet";
150
+ const name = jsxAttributeName(attribute);
151
+ if (!name) return "namespaced JSX attributes are not supported yet";
152
+ if (name === "ref" || name === "dangerouslySetInnerHTML") {
153
+ return `${name} requires React ownership`;
154
+ }
155
+ if (!types.isJSXExpressionContainer(attribute.value) || types.isJSXEmptyExpression(attribute.value.expression)) {
156
+ continue;
157
+ }
158
+ const expression = attribute.value.expression;
159
+ const dependencies = collectStateDependencies(expression, statesByValue);
160
+ if (dependencies.length === 0 || /^on[A-Z]/.test(name)) continue;
161
+ if (name === "style" || name === "children" || name === "key") {
162
+ return `stateful ${name} bindings are not supported yet`;
163
+ }
164
+ bindings.push({
165
+ kind: "attribute",
166
+ path: [...path],
167
+ dependencies,
168
+ name,
169
+ value: cloneExpression(expression)
170
+ });
171
+ }
172
+ const nestedElements = element.children.filter(
173
+ (child) => types.isJSXElement(child)
174
+ );
175
+ const expressionChildren = element.children.filter(
176
+ (child) => types.isJSXExpressionContainer(child)
177
+ );
178
+ for (const child of expressionChildren) {
179
+ if (types.isJSXEmptyExpression(child.expression)) continue;
180
+ if (!isTextExpression(child.expression)) {
181
+ return "dynamic child structures require React reconciliation";
182
+ }
183
+ }
184
+ if (nestedElements.length === 0) {
185
+ const dependencies = /* @__PURE__ */ new Set();
186
+ const parts = [];
187
+ for (const child of element.children) {
188
+ if (types.isJSXText(child)) {
189
+ const text = cleanJsxText(child.value);
190
+ if (text) parts.push(types.stringLiteral(text));
191
+ } else if (types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)) {
192
+ collectStateDependencies(child.expression, statesByValue).forEach(
193
+ (dependency) => dependencies.add(dependency)
194
+ );
195
+ parts.push(cloneExpression(child.expression));
196
+ }
197
+ }
198
+ if (dependencies.size > 0) {
199
+ bindings.push({
200
+ kind: "text",
201
+ path: [...path],
202
+ dependencies: [...dependencies].sort((left, right) => left - right),
203
+ value: types.arrayExpression(parts)
204
+ });
205
+ }
206
+ } else {
207
+ for (const child of expressionChildren) {
208
+ if (!types.isJSXEmptyExpression(child.expression) && collectStateDependencies(child.expression, statesByValue).length > 0) {
209
+ return "mixed element and stateful text children are not supported yet";
210
+ }
211
+ }
212
+ let elementIndex = 0;
213
+ for (const child of element.children) {
214
+ if (!types.isJSXElement(child)) continue;
215
+ const reason2 = visit(child, [...path, elementIndex]);
216
+ if (reason2) return reason2;
217
+ elementIndex += 1;
218
+ }
219
+ }
220
+ return void 0;
221
+ };
222
+ const reason = visit(root, []);
223
+ return reason ? { reason } : { bindings };
224
+ }
225
+ function lazyInitialValue(expression) {
226
+ const value = types.identifier("_initial");
227
+ const initializer = expression ? cloneExpression(expression) : types.identifier("undefined");
228
+ return types.callExpression(
229
+ types.arrowFunctionExpression(
230
+ [],
231
+ types.blockStatement([
232
+ types.variableDeclaration("const", [types.variableDeclarator(value, initializer)]),
233
+ types.returnStatement(
234
+ types.conditionalExpression(
235
+ types.binaryExpression(
236
+ "===",
237
+ types.unaryExpression("typeof", types.cloneNode(value)),
238
+ types.stringLiteral("function")
239
+ ),
240
+ types.callExpression(types.cloneNode(value), []),
241
+ types.cloneNode(value)
242
+ )
243
+ )
244
+ ])
245
+ ),
246
+ []
247
+ );
248
+ }
249
+ function clonePropsParameter(path) {
250
+ const parameter = path.node.params[0];
251
+ return parameter && types.isIdentifier(parameter) ? types.cloneNode(parameter, true) : types.identifier("_props");
252
+ }
253
+ function bindingObject(binding, componentPath, stateParameter, statesByValue, statesBySetter) {
254
+ const properties = [
255
+ types.objectProperty(types.identifier("kind"), types.stringLiteral(binding.kind)),
256
+ types.objectProperty(
257
+ types.identifier("path"),
258
+ types.arrayExpression(binding.path.map((part) => types.numericLiteral(part)))
259
+ ),
260
+ types.objectProperty(
261
+ types.identifier("dependencies"),
262
+ types.arrayExpression(binding.dependencies.map((part) => types.numericLiteral(part)))
263
+ )
264
+ ];
265
+ if (binding.name)
266
+ properties.push(types.objectProperty(types.identifier("name"), types.stringLiteral(binding.name)));
267
+ properties.push(
268
+ types.objectProperty(
269
+ types.identifier("read"),
270
+ types.arrowFunctionExpression(
271
+ [clonePropsParameter(componentPath), types.cloneNode(stateParameter)],
272
+ rewriteStateAccess(binding.value, stateParameter, statesByValue, statesBySetter)
273
+ )
274
+ )
275
+ );
276
+ return types.objectExpression(properties);
277
+ }
278
+ function wrapperElement(definitionIdentifier, props) {
279
+ const name = types.jsxIdentifier(definitionIdentifier.name);
280
+ const attributes = props ? [types.jsxSpreadAttribute(types.cloneNode(props))] : [];
281
+ return types.jsxElement(types.jsxOpeningElement(name, attributes, true), null, [], true);
282
+ }
283
+ function compileCandidate(candidate, createComponentIdentifier, useStateNames, reactNames) {
284
+ const { path, name, statementPath } = candidate;
285
+ if (path.node.async || path.node.generator)
286
+ return "async and generator components are not supported";
287
+ if (path.node.typeParameters) return "generic components are not supported yet";
288
+ if (path.node.params.length > 1 || path.node.params[0] && !types.isIdentifier(path.node.params[0])) {
289
+ return "components must use zero parameters or one props identifier";
290
+ }
291
+ if (!types.isBlockStatement(path.node.body)) return "components must use a block body";
292
+ const states = [];
293
+ let returned;
294
+ for (const statement of path.node.body.body) {
295
+ if (types.isReturnStatement(statement)) {
296
+ if (returned) return "components must have one unconditional return";
297
+ returned = statement;
298
+ continue;
299
+ }
300
+ if (!types.isVariableDeclaration(statement) || statement.declarations.length !== 1) {
301
+ return "only top-level useState declarations and one return are supported in Group 1";
302
+ }
303
+ const declaration = statement.declarations[0];
304
+ if (statement.kind !== "const" || !types.isArrayPattern(declaration.id) || declaration.id.elements.length !== 2 || !types.isIdentifier(declaration.id.elements[0]) || !types.isIdentifier(declaration.id.elements[1]) || !isUseStateCall(declaration.init, useStateNames, reactNames) || declaration.init.arguments.length > 1 || declaration.init.arguments[0] && !types.isExpression(declaration.init.arguments[0])) {
305
+ return "only const [value, setValue] = useState(initial) declarations are supported";
306
+ }
307
+ states.push({
308
+ valueName: declaration.id.elements[0].name,
309
+ setterName: declaration.id.elements[1].name,
310
+ index: states.length,
311
+ initialValue: declaration.init.arguments[0]
312
+ });
313
+ }
314
+ if (states.length === 0) return "no local useState binding was found";
315
+ if (!returned?.argument || !types.isJSXElement(returned.argument)) {
316
+ return "the component must return one host JSX element";
317
+ }
318
+ const statesByValue = new Map(states.map((state) => [state.valueName, state]));
319
+ const statesBySetter = new Map(states.map((state) => [state.setterName, state]));
320
+ for (const state of states) {
321
+ if (state.initialValue && (collectStateDependencies(state.initialValue, statesByValue).length > 0 || [...statesBySetter].some(
322
+ ([setterName]) => referencesIdentifier(state.initialValue, setterName)
323
+ ))) {
324
+ return "useState initializers cannot reference another local state binding";
325
+ }
326
+ }
327
+ const setterReason = validateSetterUsage(returned.argument, statesBySetter);
328
+ if (setterReason) return setterReason;
329
+ const analysis = analyzeHostTree(returned.argument, statesByValue);
330
+ if (analysis.reason) return analysis.reason;
331
+ const stateParameter = path.scope.generateUidIdentifier("farmState");
332
+ const definitionIdentifier = path.scope.generateUidIdentifier(`${name}Compiled`);
333
+ const propsParameter = clonePropsParameter(path);
334
+ const rewrittenRoot = rewriteStateAccess(
335
+ returned.argument,
336
+ stateParameter,
337
+ statesByValue,
338
+ statesBySetter
339
+ );
340
+ const definition = types.callExpression(types.cloneNode(createComponentIdentifier), [
341
+ types.objectExpression([
342
+ types.objectProperty(types.identifier("displayName"), types.stringLiteral(name)),
343
+ types.objectProperty(
344
+ types.identifier("initialize"),
345
+ types.arrowFunctionExpression(
346
+ [types.cloneNode(propsParameter)],
347
+ types.arrayExpression(states.map((state) => lazyInitialValue(state.initialValue)))
348
+ )
349
+ ),
350
+ types.objectProperty(
351
+ types.identifier("render"),
352
+ types.arrowFunctionExpression(
353
+ [types.cloneNode(propsParameter), types.cloneNode(stateParameter)],
354
+ rewrittenRoot
355
+ )
356
+ ),
357
+ types.objectProperty(
358
+ types.identifier("bindings"),
359
+ types.arrayExpression(
360
+ (analysis.bindings || []).map(
361
+ (binding) => bindingObject(binding, path, stateParameter, statesByValue, statesBySetter)
362
+ )
363
+ )
364
+ )
365
+ ])
366
+ ]);
367
+ const originalProps = path.node.params[0];
368
+ path.get("body").replaceWith(
369
+ types.blockStatement([
370
+ types.returnStatement(
371
+ wrapperElement(
372
+ definitionIdentifier,
373
+ originalProps && types.isIdentifier(originalProps) ? originalProps : void 0
374
+ )
375
+ )
376
+ ])
377
+ );
378
+ statementPath.insertAfter(
379
+ types.variableDeclaration("const", [types.variableDeclarator(definitionIdentifier, definition)])
380
+ );
381
+ return void 0;
382
+ }
383
+ function collectCandidates(programPath) {
384
+ const candidates = [];
385
+ programPath.traverse({
386
+ FunctionDeclaration(path) {
387
+ if (!path.node.id || !isComponentName(path.node.id.name)) return;
388
+ const parent = path.parentPath;
389
+ if (!parent.isProgram() && !parent.isExportNamedDeclaration() && !parent.isExportDefaultDeclaration()) {
390
+ return;
391
+ }
392
+ candidates.push({
393
+ name: path.node.id.name,
394
+ path,
395
+ statementPath: parent.isProgram() ? path : parent
396
+ });
397
+ },
398
+ VariableDeclarator(path) {
399
+ if (!types.isIdentifier(path.node.id) || !isComponentName(path.node.id.name) || !types.isFunctionExpression(path.node.init) && !types.isArrowFunctionExpression(path.node.init)) {
400
+ return;
401
+ }
402
+ const declaration = path.parentPath;
403
+ const statement = declaration.parentPath;
404
+ if (!statement) return;
405
+ const topLevel = statement.isProgram() ? declaration : statement.isExportNamedDeclaration() && statement.parentPath.isProgram() ? statement : null;
406
+ if (!topLevel) return;
407
+ candidates.push({
408
+ name: path.node.id.name,
409
+ path: path.get("init"),
410
+ statementPath: topLevel
411
+ });
412
+ }
413
+ });
414
+ return candidates;
415
+ }
416
+ async function compileReactModule(code, id, options) {
417
+ const compiled = [];
418
+ const diagnostics = [];
419
+ const plugin = () => ({
420
+ name: "farm-react-aot",
421
+ visitor: {
422
+ Program(programPath) {
423
+ const moduleDirectives = new Set(directiveValues(programPath.node));
424
+ const useStateNames = /* @__PURE__ */ new Set();
425
+ const reactNames = /* @__PURE__ */ new Set();
426
+ for (const statement of programPath.node.body) {
427
+ if (!types.isImportDeclaration(statement) || statement.source.value !== "react") continue;
428
+ for (const specifier of statement.specifiers) {
429
+ if (types.isImportDefaultSpecifier(specifier) || types.isImportNamespaceSpecifier(specifier)) {
430
+ reactNames.add(specifier.local.name);
431
+ } else if (types.isImportSpecifier(specifier) && types.isIdentifier(specifier.imported, { name: "useState" })) {
432
+ useStateNames.add(specifier.local.name);
433
+ }
434
+ }
435
+ }
436
+ const candidates = collectCandidates(programPath);
437
+ const createComponentIdentifier = programPath.scope.generateUidIdentifier("createCompiledComponent");
438
+ for (const candidate of candidates) {
439
+ const functionDirectives = new Set(
440
+ types.isBlockStatement(candidate.path.node.body) ? directiveValues(candidate.path.node.body) : []
441
+ );
442
+ const explicitlySelected = moduleDirectives.has(options.directive) || functionDirectives.has(options.directive);
443
+ if (functionDirectives.has("use no compiler")) continue;
444
+ if (options.mode === "annotation" && !explicitlySelected) continue;
445
+ const reason = compileCandidate(
446
+ candidate,
447
+ createComponentIdentifier,
448
+ useStateNames,
449
+ reactNames
450
+ );
451
+ if (reason) {
452
+ diagnostics.push({
453
+ component: candidate.name,
454
+ reason,
455
+ selected: explicitlySelected
456
+ });
457
+ } else {
458
+ compiled.push(candidate.name);
459
+ }
460
+ }
461
+ if (compiled.length > 0) {
462
+ programPath.unshiftContainer(
463
+ "body",
464
+ types.importDeclaration(
465
+ [
466
+ types.importSpecifier(
467
+ createComponentIdentifier,
468
+ types.identifier("createCompiledComponent")
469
+ )
470
+ ],
471
+ types.stringLiteral("@farm.js/react/compiler-runtime")
472
+ )
473
+ );
474
+ }
475
+ }
476
+ }
477
+ });
478
+ const result = await transformAsync(code, {
479
+ filename: id,
480
+ sourceType: "module",
481
+ ast: false,
482
+ code: true,
483
+ sourceMaps: true,
484
+ sourceFileName: id,
485
+ configFile: false,
486
+ babelrc: false,
487
+ parserOpts: {
488
+ plugins: ["jsx", "typescript"]
489
+ },
490
+ generatorOpts: {
491
+ comments: true,
492
+ compact: false
493
+ },
494
+ plugins: [plugin]
495
+ });
496
+ return {
497
+ code: result?.code || code,
498
+ map: result?.map || null,
499
+ compiled,
500
+ diagnostics
501
+ };
502
+ }
503
+
504
+ // src/index.ts
505
+ var DEFAULT_COMPILER_DIRECTIVE = "use compiler";
506
+ function normalizeReactCompilerOptions(value) {
507
+ const options = value === true ? {} : value;
508
+ const mode = options.mode || "infer";
509
+ if (mode !== "infer" && mode !== "annotation") {
510
+ throw new TypeError(`Unknown React compiler mode: ${String(mode)}`);
511
+ }
512
+ if (options.directive !== void 0 && mode !== "annotation") {
513
+ throw new TypeError("The React compiler directive can only be configured in annotation mode.");
514
+ }
515
+ const directive = options.directive?.trim() || DEFAULT_COMPILER_DIRECTIVE;
516
+ const onUnsupported = options.onUnsupported || "fallback";
517
+ if (!["fallback", "warn", "error"].includes(onUnsupported)) {
518
+ throw new TypeError(`Unknown unsupported-component behavior: ${String(onUnsupported)}`);
519
+ }
520
+ return { mode, directive, onUnsupported };
521
+ }
522
+
523
+ // src/vite.ts
524
+ function readCompilerOptions(rendererOptions) {
525
+ const experimental = rendererOptions?.experimental;
526
+ if (!experimental || typeof experimental !== "object") return false;
527
+ const compiler = experimental.compiler;
528
+ if (!compiler) return false;
529
+ if (compiler === true) return normalizeReactCompilerOptions(true);
530
+ if (typeof compiler !== "object") {
531
+ throw new TypeError(
532
+ "React experimental.compiler must be a boolean or compiler options object."
533
+ );
534
+ }
535
+ const normalized = compiler;
536
+ if ((normalized.mode === "infer" || normalized.mode === "annotation") && typeof normalized.directive === "string" && (normalized.onUnsupported === "fallback" || normalized.onUnsupported === "warn" || normalized.onUnsupported === "error")) {
537
+ return normalized;
538
+ }
539
+ return normalizeReactCompilerOptions(compiler);
540
+ }
541
+ function createFarmRendererPlugin(options = {}) {
542
+ const compilerOptions = readCompilerOptions(options.rendererOptions);
543
+ if (!compilerOptions) return [];
544
+ let projectRoot = "";
545
+ return [
546
+ {
547
+ name: "farm:react-aot-compiler",
548
+ enforce: "pre",
549
+ configResolved(config) {
550
+ projectRoot = normalizePath(config.root).replace(/\/$/, "");
551
+ },
552
+ async transform(code, id) {
553
+ const cleanId = normalizePath(id.split("?", 1)[0]);
554
+ if (!/\.[jt]sx$/.test(cleanId) || cleanId.includes("/node_modules/") || projectRoot && !cleanId.startsWith(`${projectRoot}/`))
555
+ return null;
556
+ const result = await compileReactModule(code, cleanId, compilerOptions);
557
+ for (const diagnostic of result.diagnostics) {
558
+ const message = `[react-compiler] ${diagnostic.component}: ${diagnostic.reason}; using React.`;
559
+ if (compilerOptions.onUnsupported === "error") this.error(message);
560
+ if (compilerOptions.onUnsupported === "warn" || diagnostic.selected) this.warn(message);
561
+ }
562
+ if (result.compiled.length === 0) return null;
563
+ return { code: result.code, map: result.map };
564
+ }
565
+ }
566
+ ];
567
+ }
568
+
569
+ export { createFarmRendererPlugin };
570
+ //# sourceMappingURL=vite.mjs.map
571
+ //# sourceMappingURL=vite.mjs.map