@vue-jsx-vapor/compiler 2.5.0 → 2.5.2

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/index.cjs CHANGED
@@ -756,21 +756,10 @@ function genCreateComponent(operation, context) {
756
756
  const { helper } = context;
757
757
  const tag = genTag();
758
758
  const { root, props, slots, once } = operation;
759
+ const rawProps = genRawProps(props, context);
759
760
  const rawSlots = genRawSlots(slots, context);
760
- const [ids, handlers] = processInlineHandlers(props, context);
761
- const rawProps = context.withId(() => genRawProps(props, context), ids);
762
- const inlineHandlers = handlers.reduce((acc, { name, value }) => {
763
- const handler = genEventHandler(context, value, void 0, false);
764
- return [
765
- ...acc,
766
- `const ${name} = `,
767
- ...handler,
768
- NEWLINE
769
- ];
770
- }, []);
771
761
  return [
772
762
  NEWLINE,
773
- ...inlineHandlers,
774
763
  `const n${operation.id} = `,
775
764
  ...genCall(operation.dynamic && !operation.dynamic.isStatic ? helper("createDynamicComponent") : operation.asset ? helper("createComponentWithFallback") : helper("createComponent"), tag, rawProps, rawSlots, root ? "true" : false, once && "true"),
776
765
  ...genDirectivesForElement(operation.id, context)
@@ -786,33 +775,6 @@ function genCreateComponent(operation, context) {
786
775
  else return genExpression((0, __vue_shared.extend)((0, __vue_compiler_dom.createSimpleExpression)(operation.tag, false), { ast: null }), context);
787
776
  }
788
777
  }
789
- function getUniqueHandlerName(context, name) {
790
- const { seenInlineHandlerNames } = context;
791
- const count = seenInlineHandlerNames[name] || 0;
792
- seenInlineHandlerNames[name] = count + 1;
793
- return count === 0 ? name : `${name}${count}`;
794
- }
795
- function processInlineHandlers(props, context) {
796
- const ids = Object.create(null);
797
- const handlers = [];
798
- const staticProps = props[0];
799
- if ((0, __vue_shared.isArray)(staticProps)) for (const prop of staticProps) {
800
- if (!prop.handler) continue;
801
- prop.values.forEach((value, i) => {
802
- const isMemberExp = (0, __vue_compiler_dom.isMemberExpression)(value, context.options);
803
- if (!isMemberExp) {
804
- const name = getUniqueHandlerName(context, `_on_${prop.key.content}`);
805
- handlers.push({
806
- name,
807
- value
808
- });
809
- ids[name] = null;
810
- prop.values[i] = (0, __vue_shared.extend)({ ast: null }, (0, __vue_compiler_dom.createSimpleExpression)(name));
811
- }
812
- });
813
- }
814
- return [ids, handlers];
815
- }
816
778
  function genRawProps(props, context) {
817
779
  const staticProps = props[0];
818
780
  if ((0, __vue_shared.isArray)(staticProps)) {
@@ -1068,7 +1030,33 @@ function genFor(oper, context) {
1068
1030
  idMap[rawIndex] = `${indexVar}.value`;
1069
1031
  idMap[indexVar] = null;
1070
1032
  }
1071
- const blockFn = context.withId(() => genBlock(render, context, args), idMap);
1033
+ const { selectorPatterns, keyOnlyBindingPatterns } = matchPatterns(render, keyProp, idMap);
1034
+ const selectorDeclarations = [];
1035
+ const selectorSetup = [];
1036
+ for (const [i, { selector }] of selectorPatterns.entries()) {
1037
+ const selectorName = `_selector${id}_${i}`;
1038
+ selectorDeclarations.push(`let ${selectorName}`, NEWLINE);
1039
+ if (i === 0) selectorSetup.push(`({ createSelector }) => {`, INDENT_START);
1040
+ selectorSetup.push(NEWLINE, `${selectorName} = `, ...genCall(`createSelector`, [`() => `, ...genExpression(selector, context)]));
1041
+ if (i === selectorPatterns.length - 1) selectorSetup.push(INDENT_END, NEWLINE, "}");
1042
+ }
1043
+ const blockFn = context.withId(() => {
1044
+ const frag = [];
1045
+ frag.push("(", ...args, ") => {", INDENT_START);
1046
+ if (selectorPatterns.length || keyOnlyBindingPatterns.length) frag.push(...genBlockContent(render, context, false, () => {
1047
+ const patternFrag = [];
1048
+ for (const [i, { effect }] of selectorPatterns.entries()) {
1049
+ patternFrag.push(NEWLINE, `_selector${id}_${i}(() => {`, INDENT_START);
1050
+ for (const oper$1 of effect.operations) patternFrag.push(...genOperation(oper$1, context));
1051
+ patternFrag.push(INDENT_END, NEWLINE, `})`);
1052
+ }
1053
+ for (const { effect } of keyOnlyBindingPatterns) for (const oper$1 of effect.operations) patternFrag.push(...genOperation(oper$1, context));
1054
+ return patternFrag;
1055
+ }));
1056
+ else frag.push(...genBlockContent(render, context));
1057
+ frag.push(INDENT_END, NEWLINE, "}");
1058
+ return frag;
1059
+ }, idMap);
1072
1060
  exitScope();
1073
1061
  let flags = 0;
1074
1062
  if (onlyChild) flags |= VaporVForFlags.FAST_REMOVE;
@@ -1076,8 +1064,9 @@ function genFor(oper, context) {
1076
1064
  if (once) flags |= VaporVForFlags.ONCE;
1077
1065
  return [
1078
1066
  NEWLINE,
1067
+ ...selectorDeclarations,
1079
1068
  `const n${id} = `,
1080
- ...genCall(helper("createFor"), sourceExpr, blockFn, genCallback(keyProp), flags ? String(flags) : void 0)
1069
+ ...genCall([helper("createFor"), "undefined"], sourceExpr, blockFn, genCallback(keyProp), flags ? String(flags) : void 0, selectorSetup.length ? selectorSetup : void 0)
1081
1070
  ];
1082
1071
  function parseValueDestructure() {
1083
1072
  const map = /* @__PURE__ */ new Map();
@@ -1151,6 +1140,131 @@ function genFor(oper, context) {
1151
1140
  return idMap$1;
1152
1141
  }
1153
1142
  }
1143
+ function matchPatterns(render, keyProp, idMap) {
1144
+ const selectorPatterns = [];
1145
+ const keyOnlyBindingPatterns = [];
1146
+ render.effect = render.effect.filter((effect) => {
1147
+ if (keyProp !== void 0) {
1148
+ const selector = matchSelectorPattern(effect, keyProp.ast, idMap);
1149
+ if (selector) {
1150
+ selectorPatterns.push(selector);
1151
+ return false;
1152
+ }
1153
+ const keyOnly = matchKeyOnlyBindingPattern(effect, keyProp.ast);
1154
+ if (keyOnly) {
1155
+ keyOnlyBindingPatterns.push(keyOnly);
1156
+ return false;
1157
+ }
1158
+ }
1159
+ return true;
1160
+ });
1161
+ return {
1162
+ keyOnlyBindingPatterns,
1163
+ selectorPatterns
1164
+ };
1165
+ }
1166
+ function matchKeyOnlyBindingPattern(effect, keyAst) {
1167
+ if (effect.expressions.length === 1) {
1168
+ const ast = effect.expressions[0].ast;
1169
+ if (typeof ast === "object" && ast !== null && isKeyOnlyBinding(ast, keyAst)) return { effect };
1170
+ }
1171
+ }
1172
+ function matchSelectorPattern(effect, keyAst, idMap) {
1173
+ if (effect.expressions.length === 1) {
1174
+ const ast = effect.expressions[0].ast;
1175
+ const offset = effect.expressions[0].loc.start.offset;
1176
+ if (typeof ast === "object" && ast) {
1177
+ const matcheds = [];
1178
+ (0, ast_kit.walkAST)(ast, { enter(node) {
1179
+ if (typeof node === "object" && node && node.type === "BinaryExpression" && node.operator === "===" && node.left.type !== "PrivateName") {
1180
+ const { left, right } = node;
1181
+ for (const [a, b] of [[left, right], [right, left]]) {
1182
+ const aIsKey = isKeyOnlyBinding(a, keyAst);
1183
+ const bIsKey = isKeyOnlyBinding(b, keyAst);
1184
+ const bVars = analyzeVariableScopes(b, idMap);
1185
+ if (aIsKey && !bIsKey && !bVars.locals.length) matcheds.push([a, b]);
1186
+ }
1187
+ }
1188
+ } });
1189
+ if (matcheds.length === 1) {
1190
+ const [key, selector] = matcheds[0];
1191
+ const content$1 = effect.expressions[0].content;
1192
+ let hasExtraId = false;
1193
+ const parentStackMap = /* @__PURE__ */ new Map();
1194
+ const parentStack = [];
1195
+ (0, __vue_compiler_dom.walkIdentifiers)(ast, (id) => {
1196
+ if (id.start !== key.start && id.start !== selector.start) hasExtraId = true;
1197
+ parentStackMap.set(id, parentStack.slice());
1198
+ }, false, parentStack);
1199
+ if (!hasExtraId) {
1200
+ const name = content$1.slice(selector.start - offset, selector.end - offset);
1201
+ return {
1202
+ effect,
1203
+ selector: {
1204
+ content: name,
1205
+ ast: (0, __vue_shared.extend)({}, selector, {
1206
+ start: 1,
1207
+ end: name.length + 1
1208
+ }),
1209
+ loc: selector.loc,
1210
+ isStatic: false
1211
+ }
1212
+ };
1213
+ }
1214
+ }
1215
+ }
1216
+ const content = effect.expressions[0].content;
1217
+ if (typeof ast === "object" && ast && ast.type === "ConditionalExpression" && ast.test.type === "BinaryExpression" && ast.test.operator === "===" && ast.test.left.type !== "PrivateName" && (0, __vue_compiler_dom.isStaticNode)(ast.consequent) && (0, __vue_compiler_dom.isStaticNode)(ast.alternate)) {
1218
+ const left = ast.test.left;
1219
+ const right = ast.test.right;
1220
+ for (const [a, b] of [[left, right], [right, left]]) {
1221
+ const aIsKey = isKeyOnlyBinding(a, keyAst);
1222
+ const bIsKey = isKeyOnlyBinding(b, keyAst);
1223
+ const bVars = analyzeVariableScopes(b, idMap);
1224
+ if (aIsKey && !bIsKey && !bVars.locals.length) return {
1225
+ effect,
1226
+ selector: {
1227
+ content: content.slice(b.start - offset, b.end - offset),
1228
+ ast: b,
1229
+ loc: b.loc,
1230
+ isStatic: false
1231
+ }
1232
+ };
1233
+ }
1234
+ }
1235
+ }
1236
+ }
1237
+ function analyzeVariableScopes(ast, idMap) {
1238
+ const globals = [];
1239
+ const locals = [];
1240
+ const ids = [];
1241
+ const parentStackMap = /* @__PURE__ */ new Map();
1242
+ const parentStack = [];
1243
+ (0, __vue_compiler_dom.walkIdentifiers)(ast, (id) => {
1244
+ ids.push(id);
1245
+ parentStackMap.set(id, parentStack.slice());
1246
+ }, false, parentStack);
1247
+ for (const id of ids) {
1248
+ if ((0, __vue_shared.isGloballyAllowed)(id.name)) continue;
1249
+ if (idMap[id.name]) locals.push(id.name);
1250
+ else globals.push(id.name);
1251
+ }
1252
+ return {
1253
+ globals,
1254
+ locals
1255
+ };
1256
+ }
1257
+ function isKeyOnlyBinding(expr, keyAst) {
1258
+ let only = true;
1259
+ (0, ast_kit.walkAST)(expr, { enter(node) {
1260
+ if ((0, __babel_types.isNodesEquivalent)(node, keyAst)) {
1261
+ this.skip();
1262
+ return;
1263
+ }
1264
+ if (node.type === "Identifier") only = false;
1265
+ } });
1266
+ return only;
1267
+ }
1154
1268
 
1155
1269
  //#endregion
1156
1270
  //#region src/generators/html.ts
@@ -1267,7 +1381,7 @@ function genOperation(oper, context) {
1267
1381
  }
1268
1382
  }
1269
1383
  }
1270
- function genEffects(effects, context) {
1384
+ function genEffects(effects, context, genExtraFrag) {
1271
1385
  const { helper } = context;
1272
1386
  const [frag, push, unshift] = buildCodeFragment();
1273
1387
  let operationsCount = 0;
@@ -1287,6 +1401,7 @@ function genEffects(effects, context) {
1287
1401
  unshift(NEWLINE, `${helper("renderEffect")}(() => `);
1288
1402
  push(`)`);
1289
1403
  }
1404
+ if (genExtraFrag) push(...context.withId(genExtraFrag, {}));
1290
1405
  return frag;
1291
1406
  }
1292
1407
  function genEffect({ operations }, context) {
@@ -1353,19 +1468,19 @@ function genChildren(dynamic, context, pushBlock, from = `n${dynamic.id}`) {
1353
1468
 
1354
1469
  //#endregion
1355
1470
  //#region src/generators/block.ts
1356
- function genBlock(oper, context, args = [], root, customReturns) {
1471
+ function genBlock(oper, context, args = [], root) {
1357
1472
  return [
1358
1473
  "(",
1359
1474
  ...args,
1360
1475
  ") => {",
1361
1476
  INDENT_START,
1362
- ...genBlockContent(oper, context, root, customReturns),
1477
+ ...genBlockContent(oper, context, root),
1363
1478
  INDENT_END,
1364
1479
  NEWLINE,
1365
1480
  "}"
1366
1481
  ];
1367
1482
  }
1368
- function genBlockContent(block, context, root, customReturns) {
1483
+ function genBlockContent(block, context, root, genEffectsExtraFrag) {
1369
1484
  const [frag, push] = buildCodeFragment();
1370
1485
  const { dynamic, effect, operation, returns } = block;
1371
1486
  const resetBlock = context.enterBlock(block);
@@ -1381,11 +1496,11 @@ function genBlockContent(block, context, root, customReturns) {
1381
1496
  for (const child of dynamic.children) push(...genSelf(child, context));
1382
1497
  for (const child of dynamic.children) push(...genChildren(child, context, push, `n${child.id}`));
1383
1498
  push(...genOperations(operation, context));
1384
- push(...genEffects(effect, context));
1499
+ push(...genEffects(effect, context, genEffectsExtraFrag));
1385
1500
  push(NEWLINE, `return `);
1386
1501
  const returnNodes = returns.map((n) => `n${n}`);
1387
1502
  const returnsCode = returnNodes.length > 1 ? genMulti(DELIMITERS_ARRAY, ...returnNodes) : [returnNodes[0] || "null"];
1388
- push(...customReturns ? customReturns(returnsCode) : returnsCode);
1503
+ push(...returnsCode);
1389
1504
  resetBlock();
1390
1505
  return frag;
1391
1506
  function genResolveAssets(kind, helper) {
@@ -1404,7 +1519,6 @@ var CodegenContext = class {
1404
1519
  };
1405
1520
  delegates = /* @__PURE__ */ new Set();
1406
1521
  identifiers = Object.create(null);
1407
- seenInlineHandlerNames = Object.create(null);
1408
1522
  block;
1409
1523
  withId(fn, map) {
1410
1524
  const { identifiers } = this;
@@ -2273,9 +2387,9 @@ function hasDynamicKeyVBind(node) {
2273
2387
  const delegatedEvents = /* @__PURE__ */ (0, __vue_shared.makeMap)("beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,keyup,mousedown,mousemove,mouseout,mouseover,mouseup,pointerdown,pointermove,pointerout,pointerover,pointerup,touchend,touchmove,touchstart");
2274
2388
  const transformVOn = (dir, node, context) => {
2275
2389
  const { name, loc, value } = dir;
2276
- if (name.type === "JSXNamespacedName") return;
2390
+ if (!name) return;
2277
2391
  const isComponent = isJSXComponent(node);
2278
- const [nameString, ...modifiers] = name.name.replace(/^on([A-Z])/, (_, $1) => $1.toLowerCase()).split("_");
2392
+ const [nameString, ...modifiers] = context.ir.source.slice(name.start, name.end).replace(/^on([A-Z])/, (_, $1) => $1.toLowerCase()).split("_");
2279
2393
  if (!value && !modifiers.length) context.options.onError((0, __vue_compiler_dom.createCompilerError)(__vue_compiler_dom.ErrorCodes.X_V_ON_NO_EXPRESSION, resolveLocation(loc, context)));
2280
2394
  let arg = resolveSimpleExpression(nameString, true, dir.name.loc);
2281
2395
  const exp = resolveExpression(dir.value, context);
@@ -2473,13 +2587,10 @@ function createSlotBlock(slotNode, dir, context) {
2473
2587
  //#region src/transforms/vSlots.ts
2474
2588
  const transformVSlots = (dir, node, context) => {
2475
2589
  if (!isJSXComponent(node)) return;
2476
- if (dir.value?.type === "JSXExpressionContainer") {
2477
- context.slots = [{
2478
- slotType: IRSlotType.EXPRESSION,
2479
- slots: resolveExpression(dir.value.expression, context)
2480
- }];
2481
- if (node.children.length) context.options.onError((0, __vue_compiler_dom.createCompilerError)(__vue_compiler_dom.ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, resolveLocation(node.children[0].loc, context)));
2482
- }
2590
+ if (dir.value?.type === "JSXExpressionContainer") context.slots = [{
2591
+ slotType: IRSlotType.EXPRESSION,
2592
+ slots: resolveExpression(dir.value.expression, context)
2593
+ }];
2483
2594
  };
2484
2595
 
2485
2596
  //#endregion
package/dist/index.d.cts CHANGED
@@ -353,7 +353,6 @@ declare class CodegenContext {
353
353
  helper: (name: string) => string;
354
354
  delegates: Set<string>;
355
355
  identifiers: Record<string, (string | SimpleExpressionNode)[]>;
356
- seenInlineHandlerNames: Record<string, number>;
357
356
  block: BlockIRNode;
358
357
  withId<T>(fn: () => T, map: Record<string, string | SimpleExpressionNode | null>): T;
359
358
  enterBlock(block: BlockIRNode): () => BlockIRNode;
package/dist/index.d.ts CHANGED
@@ -353,7 +353,6 @@ declare class CodegenContext {
353
353
  helper: (name: string) => string;
354
354
  delegates: Set<string>;
355
355
  identifiers: Record<string, (string | SimpleExpressionNode)[]>;
356
- seenInlineHandlerNames: Record<string, number>;
357
356
  block: BlockIRNode;
358
357
  withId<T>(fn: () => T, map: Record<string, string | SimpleExpressionNode | null>): T;
359
358
  enterBlock(block: BlockIRNode): () => BlockIRNode;
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { parse, parseExpression } from "@babel/parser";
2
2
  import { NOOP, camelize, canSetValueDirectly, capitalize, extend, isArray, isBuiltInDirective, isGloballyAllowed, isHTMLTag, isSVGTag, isString, isVoidTag, makeMap, remove, shouldSetAsAttr, toHandlerKey } from "@vue/shared";
3
3
  import { DOMErrorCodes, ErrorCodes, NewlineType, NodeTypes, TS_NODE_TYPES, advancePositionWithClone, advancePositionWithMutation, createCompilerError, createDOMCompilerError, createSimpleExpression, defaultOnError, defaultOnWarn, isConstantNode, isFnExpression, isLiteralWhitelisted, isMemberExpression, isSimpleIdentifier, isStaticNode, isStaticProperty, isValidHTMLNesting, locStub, resolveModifiers, toValidAssetId, unwrapTSNode, walkIdentifiers } from "@vue/compiler-dom";
4
- import { walkIdentifiers as walkIdentifiers$1 } from "ast-kit";
5
- import { isLiteral, jsxClosingFragment, jsxExpressionContainer, jsxFragment, jsxOpeningFragment } from "@babel/types";
4
+ import { walkAST, walkIdentifiers as walkIdentifiers$1 } from "ast-kit";
5
+ import { isLiteral, isNodesEquivalent, jsxClosingFragment, jsxExpressionContainer, jsxFragment, jsxOpeningFragment } from "@babel/types";
6
6
  import { SourceMapGenerator } from "source-map-js";
7
7
 
8
8
  //#region src/ir/component.ts
@@ -733,21 +733,10 @@ function genCreateComponent(operation, context) {
733
733
  const { helper } = context;
734
734
  const tag = genTag();
735
735
  const { root, props, slots, once } = operation;
736
+ const rawProps = genRawProps(props, context);
736
737
  const rawSlots = genRawSlots(slots, context);
737
- const [ids, handlers] = processInlineHandlers(props, context);
738
- const rawProps = context.withId(() => genRawProps(props, context), ids);
739
- const inlineHandlers = handlers.reduce((acc, { name, value }) => {
740
- const handler = genEventHandler(context, value, void 0, false);
741
- return [
742
- ...acc,
743
- `const ${name} = `,
744
- ...handler,
745
- NEWLINE
746
- ];
747
- }, []);
748
738
  return [
749
739
  NEWLINE,
750
- ...inlineHandlers,
751
740
  `const n${operation.id} = `,
752
741
  ...genCall(operation.dynamic && !operation.dynamic.isStatic ? helper("createDynamicComponent") : operation.asset ? helper("createComponentWithFallback") : helper("createComponent"), tag, rawProps, rawSlots, root ? "true" : false, once && "true"),
753
742
  ...genDirectivesForElement(operation.id, context)
@@ -763,33 +752,6 @@ function genCreateComponent(operation, context) {
763
752
  else return genExpression(extend(createSimpleExpression(operation.tag, false), { ast: null }), context);
764
753
  }
765
754
  }
766
- function getUniqueHandlerName(context, name) {
767
- const { seenInlineHandlerNames } = context;
768
- const count = seenInlineHandlerNames[name] || 0;
769
- seenInlineHandlerNames[name] = count + 1;
770
- return count === 0 ? name : `${name}${count}`;
771
- }
772
- function processInlineHandlers(props, context) {
773
- const ids = Object.create(null);
774
- const handlers = [];
775
- const staticProps = props[0];
776
- if (isArray(staticProps)) for (const prop of staticProps) {
777
- if (!prop.handler) continue;
778
- prop.values.forEach((value, i) => {
779
- const isMemberExp = isMemberExpression(value, context.options);
780
- if (!isMemberExp) {
781
- const name = getUniqueHandlerName(context, `_on_${prop.key.content}`);
782
- handlers.push({
783
- name,
784
- value
785
- });
786
- ids[name] = null;
787
- prop.values[i] = extend({ ast: null }, createSimpleExpression(name));
788
- }
789
- });
790
- }
791
- return [ids, handlers];
792
- }
793
755
  function genRawProps(props, context) {
794
756
  const staticProps = props[0];
795
757
  if (isArray(staticProps)) {
@@ -1045,7 +1007,33 @@ function genFor(oper, context) {
1045
1007
  idMap[rawIndex] = `${indexVar}.value`;
1046
1008
  idMap[indexVar] = null;
1047
1009
  }
1048
- const blockFn = context.withId(() => genBlock(render, context, args), idMap);
1010
+ const { selectorPatterns, keyOnlyBindingPatterns } = matchPatterns(render, keyProp, idMap);
1011
+ const selectorDeclarations = [];
1012
+ const selectorSetup = [];
1013
+ for (const [i, { selector }] of selectorPatterns.entries()) {
1014
+ const selectorName = `_selector${id}_${i}`;
1015
+ selectorDeclarations.push(`let ${selectorName}`, NEWLINE);
1016
+ if (i === 0) selectorSetup.push(`({ createSelector }) => {`, INDENT_START);
1017
+ selectorSetup.push(NEWLINE, `${selectorName} = `, ...genCall(`createSelector`, [`() => `, ...genExpression(selector, context)]));
1018
+ if (i === selectorPatterns.length - 1) selectorSetup.push(INDENT_END, NEWLINE, "}");
1019
+ }
1020
+ const blockFn = context.withId(() => {
1021
+ const frag = [];
1022
+ frag.push("(", ...args, ") => {", INDENT_START);
1023
+ if (selectorPatterns.length || keyOnlyBindingPatterns.length) frag.push(...genBlockContent(render, context, false, () => {
1024
+ const patternFrag = [];
1025
+ for (const [i, { effect }] of selectorPatterns.entries()) {
1026
+ patternFrag.push(NEWLINE, `_selector${id}_${i}(() => {`, INDENT_START);
1027
+ for (const oper$1 of effect.operations) patternFrag.push(...genOperation(oper$1, context));
1028
+ patternFrag.push(INDENT_END, NEWLINE, `})`);
1029
+ }
1030
+ for (const { effect } of keyOnlyBindingPatterns) for (const oper$1 of effect.operations) patternFrag.push(...genOperation(oper$1, context));
1031
+ return patternFrag;
1032
+ }));
1033
+ else frag.push(...genBlockContent(render, context));
1034
+ frag.push(INDENT_END, NEWLINE, "}");
1035
+ return frag;
1036
+ }, idMap);
1049
1037
  exitScope();
1050
1038
  let flags = 0;
1051
1039
  if (onlyChild) flags |= VaporVForFlags.FAST_REMOVE;
@@ -1053,8 +1041,9 @@ function genFor(oper, context) {
1053
1041
  if (once) flags |= VaporVForFlags.ONCE;
1054
1042
  return [
1055
1043
  NEWLINE,
1044
+ ...selectorDeclarations,
1056
1045
  `const n${id} = `,
1057
- ...genCall(helper("createFor"), sourceExpr, blockFn, genCallback(keyProp), flags ? String(flags) : void 0)
1046
+ ...genCall([helper("createFor"), "undefined"], sourceExpr, blockFn, genCallback(keyProp), flags ? String(flags) : void 0, selectorSetup.length ? selectorSetup : void 0)
1058
1047
  ];
1059
1048
  function parseValueDestructure() {
1060
1049
  const map = /* @__PURE__ */ new Map();
@@ -1128,6 +1117,131 @@ function genFor(oper, context) {
1128
1117
  return idMap$1;
1129
1118
  }
1130
1119
  }
1120
+ function matchPatterns(render, keyProp, idMap) {
1121
+ const selectorPatterns = [];
1122
+ const keyOnlyBindingPatterns = [];
1123
+ render.effect = render.effect.filter((effect) => {
1124
+ if (keyProp !== void 0) {
1125
+ const selector = matchSelectorPattern(effect, keyProp.ast, idMap);
1126
+ if (selector) {
1127
+ selectorPatterns.push(selector);
1128
+ return false;
1129
+ }
1130
+ const keyOnly = matchKeyOnlyBindingPattern(effect, keyProp.ast);
1131
+ if (keyOnly) {
1132
+ keyOnlyBindingPatterns.push(keyOnly);
1133
+ return false;
1134
+ }
1135
+ }
1136
+ return true;
1137
+ });
1138
+ return {
1139
+ keyOnlyBindingPatterns,
1140
+ selectorPatterns
1141
+ };
1142
+ }
1143
+ function matchKeyOnlyBindingPattern(effect, keyAst) {
1144
+ if (effect.expressions.length === 1) {
1145
+ const ast = effect.expressions[0].ast;
1146
+ if (typeof ast === "object" && ast !== null && isKeyOnlyBinding(ast, keyAst)) return { effect };
1147
+ }
1148
+ }
1149
+ function matchSelectorPattern(effect, keyAst, idMap) {
1150
+ if (effect.expressions.length === 1) {
1151
+ const ast = effect.expressions[0].ast;
1152
+ const offset = effect.expressions[0].loc.start.offset;
1153
+ if (typeof ast === "object" && ast) {
1154
+ const matcheds = [];
1155
+ walkAST(ast, { enter(node) {
1156
+ if (typeof node === "object" && node && node.type === "BinaryExpression" && node.operator === "===" && node.left.type !== "PrivateName") {
1157
+ const { left, right } = node;
1158
+ for (const [a, b] of [[left, right], [right, left]]) {
1159
+ const aIsKey = isKeyOnlyBinding(a, keyAst);
1160
+ const bIsKey = isKeyOnlyBinding(b, keyAst);
1161
+ const bVars = analyzeVariableScopes(b, idMap);
1162
+ if (aIsKey && !bIsKey && !bVars.locals.length) matcheds.push([a, b]);
1163
+ }
1164
+ }
1165
+ } });
1166
+ if (matcheds.length === 1) {
1167
+ const [key, selector] = matcheds[0];
1168
+ const content$1 = effect.expressions[0].content;
1169
+ let hasExtraId = false;
1170
+ const parentStackMap = /* @__PURE__ */ new Map();
1171
+ const parentStack = [];
1172
+ walkIdentifiers(ast, (id) => {
1173
+ if (id.start !== key.start && id.start !== selector.start) hasExtraId = true;
1174
+ parentStackMap.set(id, parentStack.slice());
1175
+ }, false, parentStack);
1176
+ if (!hasExtraId) {
1177
+ const name = content$1.slice(selector.start - offset, selector.end - offset);
1178
+ return {
1179
+ effect,
1180
+ selector: {
1181
+ content: name,
1182
+ ast: extend({}, selector, {
1183
+ start: 1,
1184
+ end: name.length + 1
1185
+ }),
1186
+ loc: selector.loc,
1187
+ isStatic: false
1188
+ }
1189
+ };
1190
+ }
1191
+ }
1192
+ }
1193
+ const content = effect.expressions[0].content;
1194
+ if (typeof ast === "object" && ast && ast.type === "ConditionalExpression" && ast.test.type === "BinaryExpression" && ast.test.operator === "===" && ast.test.left.type !== "PrivateName" && isStaticNode(ast.consequent) && isStaticNode(ast.alternate)) {
1195
+ const left = ast.test.left;
1196
+ const right = ast.test.right;
1197
+ for (const [a, b] of [[left, right], [right, left]]) {
1198
+ const aIsKey = isKeyOnlyBinding(a, keyAst);
1199
+ const bIsKey = isKeyOnlyBinding(b, keyAst);
1200
+ const bVars = analyzeVariableScopes(b, idMap);
1201
+ if (aIsKey && !bIsKey && !bVars.locals.length) return {
1202
+ effect,
1203
+ selector: {
1204
+ content: content.slice(b.start - offset, b.end - offset),
1205
+ ast: b,
1206
+ loc: b.loc,
1207
+ isStatic: false
1208
+ }
1209
+ };
1210
+ }
1211
+ }
1212
+ }
1213
+ }
1214
+ function analyzeVariableScopes(ast, idMap) {
1215
+ const globals = [];
1216
+ const locals = [];
1217
+ const ids = [];
1218
+ const parentStackMap = /* @__PURE__ */ new Map();
1219
+ const parentStack = [];
1220
+ walkIdentifiers(ast, (id) => {
1221
+ ids.push(id);
1222
+ parentStackMap.set(id, parentStack.slice());
1223
+ }, false, parentStack);
1224
+ for (const id of ids) {
1225
+ if (isGloballyAllowed(id.name)) continue;
1226
+ if (idMap[id.name]) locals.push(id.name);
1227
+ else globals.push(id.name);
1228
+ }
1229
+ return {
1230
+ globals,
1231
+ locals
1232
+ };
1233
+ }
1234
+ function isKeyOnlyBinding(expr, keyAst) {
1235
+ let only = true;
1236
+ walkAST(expr, { enter(node) {
1237
+ if (isNodesEquivalent(node, keyAst)) {
1238
+ this.skip();
1239
+ return;
1240
+ }
1241
+ if (node.type === "Identifier") only = false;
1242
+ } });
1243
+ return only;
1244
+ }
1131
1245
 
1132
1246
  //#endregion
1133
1247
  //#region src/generators/html.ts
@@ -1244,7 +1358,7 @@ function genOperation(oper, context) {
1244
1358
  }
1245
1359
  }
1246
1360
  }
1247
- function genEffects(effects, context) {
1361
+ function genEffects(effects, context, genExtraFrag) {
1248
1362
  const { helper } = context;
1249
1363
  const [frag, push, unshift] = buildCodeFragment();
1250
1364
  let operationsCount = 0;
@@ -1264,6 +1378,7 @@ function genEffects(effects, context) {
1264
1378
  unshift(NEWLINE, `${helper("renderEffect")}(() => `);
1265
1379
  push(`)`);
1266
1380
  }
1381
+ if (genExtraFrag) push(...context.withId(genExtraFrag, {}));
1267
1382
  return frag;
1268
1383
  }
1269
1384
  function genEffect({ operations }, context) {
@@ -1330,19 +1445,19 @@ function genChildren(dynamic, context, pushBlock, from = `n${dynamic.id}`) {
1330
1445
 
1331
1446
  //#endregion
1332
1447
  //#region src/generators/block.ts
1333
- function genBlock(oper, context, args = [], root, customReturns) {
1448
+ function genBlock(oper, context, args = [], root) {
1334
1449
  return [
1335
1450
  "(",
1336
1451
  ...args,
1337
1452
  ") => {",
1338
1453
  INDENT_START,
1339
- ...genBlockContent(oper, context, root, customReturns),
1454
+ ...genBlockContent(oper, context, root),
1340
1455
  INDENT_END,
1341
1456
  NEWLINE,
1342
1457
  "}"
1343
1458
  ];
1344
1459
  }
1345
- function genBlockContent(block, context, root, customReturns) {
1460
+ function genBlockContent(block, context, root, genEffectsExtraFrag) {
1346
1461
  const [frag, push] = buildCodeFragment();
1347
1462
  const { dynamic, effect, operation, returns } = block;
1348
1463
  const resetBlock = context.enterBlock(block);
@@ -1358,11 +1473,11 @@ function genBlockContent(block, context, root, customReturns) {
1358
1473
  for (const child of dynamic.children) push(...genSelf(child, context));
1359
1474
  for (const child of dynamic.children) push(...genChildren(child, context, push, `n${child.id}`));
1360
1475
  push(...genOperations(operation, context));
1361
- push(...genEffects(effect, context));
1476
+ push(...genEffects(effect, context, genEffectsExtraFrag));
1362
1477
  push(NEWLINE, `return `);
1363
1478
  const returnNodes = returns.map((n) => `n${n}`);
1364
1479
  const returnsCode = returnNodes.length > 1 ? genMulti(DELIMITERS_ARRAY, ...returnNodes) : [returnNodes[0] || "null"];
1365
- push(...customReturns ? customReturns(returnsCode) : returnsCode);
1480
+ push(...returnsCode);
1366
1481
  resetBlock();
1367
1482
  return frag;
1368
1483
  function genResolveAssets(kind, helper) {
@@ -1381,7 +1496,6 @@ var CodegenContext = class {
1381
1496
  };
1382
1497
  delegates = /* @__PURE__ */ new Set();
1383
1498
  identifiers = Object.create(null);
1384
- seenInlineHandlerNames = Object.create(null);
1385
1499
  block;
1386
1500
  withId(fn, map) {
1387
1501
  const { identifiers } = this;
@@ -2250,9 +2364,9 @@ function hasDynamicKeyVBind(node) {
2250
2364
  const delegatedEvents = /* @__PURE__ */ makeMap("beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,keyup,mousedown,mousemove,mouseout,mouseover,mouseup,pointerdown,pointermove,pointerout,pointerover,pointerup,touchend,touchmove,touchstart");
2251
2365
  const transformVOn = (dir, node, context) => {
2252
2366
  const { name, loc, value } = dir;
2253
- if (name.type === "JSXNamespacedName") return;
2367
+ if (!name) return;
2254
2368
  const isComponent = isJSXComponent(node);
2255
- const [nameString, ...modifiers] = name.name.replace(/^on([A-Z])/, (_, $1) => $1.toLowerCase()).split("_");
2369
+ const [nameString, ...modifiers] = context.ir.source.slice(name.start, name.end).replace(/^on([A-Z])/, (_, $1) => $1.toLowerCase()).split("_");
2256
2370
  if (!value && !modifiers.length) context.options.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, resolveLocation(loc, context)));
2257
2371
  let arg = resolveSimpleExpression(nameString, true, dir.name.loc);
2258
2372
  const exp = resolveExpression(dir.value, context);
@@ -2450,13 +2564,10 @@ function createSlotBlock(slotNode, dir, context) {
2450
2564
  //#region src/transforms/vSlots.ts
2451
2565
  const transformVSlots = (dir, node, context) => {
2452
2566
  if (!isJSXComponent(node)) return;
2453
- if (dir.value?.type === "JSXExpressionContainer") {
2454
- context.slots = [{
2455
- slotType: IRSlotType.EXPRESSION,
2456
- slots: resolveExpression(dir.value.expression, context)
2457
- }];
2458
- if (node.children.length) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, resolveLocation(node.children[0].loc, context)));
2459
- }
2567
+ if (dir.value?.type === "JSXExpressionContainer") context.slots = [{
2568
+ slotType: IRSlotType.EXPRESSION,
2569
+ slots: resolveExpression(dir.value.expression, context)
2570
+ }];
2460
2571
  };
2461
2572
 
2462
2573
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-jsx-vapor/compiler",
3
- "version": "2.5.0",
3
+ "version": "2.5.2",
4
4
  "description": "Vue JSX Vapor Compiler",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -36,8 +36,8 @@
36
36
  "dependencies": {
37
37
  "@babel/parser": "^7.28.0",
38
38
  "@babel/types": "^7.28.0",
39
- "@vue/compiler-dom": "https://pkg.pr.new/@vue/compiler-dom@51677cd",
40
- "@vue/shared": "https://pkg.pr.new/@vue/shared@51677cd",
39
+ "@vue/compiler-dom": "https://pkg.pr.new/@vue/compiler-dom@5771104",
40
+ "@vue/shared": "https://pkg.pr.new/@vue/shared@5771104",
41
41
  "ast-kit": "^2.1.1",
42
42
  "source-map-js": "^1.2.1"
43
43
  },