@hyperframes/parsers 0.7.92 → 0.7.93

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.
@@ -518,8 +518,79 @@ function containsTimelineCall(node, timelineVar) {
518
518
  function rangeOf(node) {
519
519
  return typeof node.start === "number" && typeof node.end === "number" ? [node.start, node.end] : void 0;
520
520
  }
521
+ var SAFE_DEFAULT_NODES = /* @__PURE__ */ new Set([
522
+ "ArrayExpression",
523
+ "BinaryExpression",
524
+ "ChainExpression",
525
+ "ConditionalExpression",
526
+ "Identifier",
527
+ "Literal",
528
+ "LogicalExpression",
529
+ "MemberExpression",
530
+ "ObjectExpression",
531
+ "Property",
532
+ "SpreadElement",
533
+ "TemplateElement",
534
+ "TemplateLiteral",
535
+ "UnaryExpression"
536
+ ]);
537
+ function isSafeDefaultExpression(node, earlierParams) {
538
+ let safe = true;
539
+ const visit = (current, parent, key) => {
540
+ if (!isNode(current) || !safe) return;
541
+ if (!SAFE_DEFAULT_NODES.has(current.type)) {
542
+ safe = false;
543
+ return;
544
+ }
545
+ if (current.type === "UnaryExpression" && current.operator === "delete") {
546
+ safe = false;
547
+ return;
548
+ }
549
+ if (current.type === "Identifier") {
550
+ const nonValue = parent && key ? isNonValueIdentifierSlot(parent, key) : false;
551
+ if (!nonValue && current.name !== "undefined" && !earlierParams.has(current.name)) {
552
+ safe = false;
553
+ }
554
+ return;
555
+ }
556
+ for (const childKey of Object.keys(current)) {
557
+ if (SKIP_KEYS.has(childKey)) continue;
558
+ const child = current[childKey];
559
+ if (Array.isArray(child)) {
560
+ for (const item of child) visit(item, current, childKey);
561
+ } else {
562
+ visit(child, current, childKey);
563
+ }
564
+ }
565
+ };
566
+ visit(node);
567
+ return safe;
568
+ }
569
+ var SUPPORTED_PARAMS_CACHE = /* @__PURE__ */ new WeakMap();
570
+ function supportedParam(param, earlier) {
571
+ if (param.type === "Identifier") return { name: param.name };
572
+ if (param.type !== "AssignmentPattern" || param.left?.type !== "Identifier") return null;
573
+ if (!isSafeDefaultExpression(param.right, earlier)) return null;
574
+ return { name: param.left.name, defaultExpression: param.right };
575
+ }
576
+ function supportedParams(fn) {
577
+ if (SUPPORTED_PARAMS_CACHE.has(fn)) return SUPPORTED_PARAMS_CACHE.get(fn) ?? null;
578
+ const params = [];
579
+ const earlier = /* @__PURE__ */ new Set();
580
+ for (const param of fn.params ?? []) {
581
+ const parsed = supportedParam(param, earlier);
582
+ if (!parsed) {
583
+ SUPPORTED_PARAMS_CACHE.set(fn, null);
584
+ return null;
585
+ }
586
+ params.push(parsed);
587
+ earlier.add(parsed.name);
588
+ }
589
+ SUPPORTED_PARAMS_CACHE.set(fn, params);
590
+ return params;
591
+ }
521
592
  function isShapeEligible(fn) {
522
- return isFunctionNode(fn) && fn.body?.type === "BlockStatement" && !(fn.params ?? []).some((p) => p.type !== "Identifier");
593
+ return isFunctionNode(fn) && fn.body?.type === "BlockStatement" && supportedParams(fn) !== null;
523
594
  }
524
595
  function callsAny(node, names) {
525
596
  let hit = false;
@@ -569,20 +640,55 @@ function timelineBuildingNames(candidates, timelineVar) {
569
640
  function bump(counts, key) {
570
641
  counts.set(key, (counts.get(key) ?? 0) + 1);
571
642
  }
643
+ function undefinedIdentifier() {
644
+ return { type: "Identifier", name: "undefined" };
645
+ }
646
+ function isExplicitUndefined(node) {
647
+ return node?.type === "Identifier" && node.name === "undefined" || node?.type === "UnaryExpression" && node.operator === "void" && node.argument?.type === "Literal" && node.argument.value === 0;
648
+ }
649
+ function resolveHelperBindings(call, params) {
650
+ if (call.arguments?.some((arg) => arg?.type === "SpreadElement")) return null;
651
+ const bindings = /* @__PURE__ */ new Map();
652
+ for (let i = 0; i < params.length; i++) {
653
+ const param = params[i];
654
+ const arg = call.arguments?.[i];
655
+ if (arg && !isExplicitUndefined(arg)) {
656
+ bindings.set(param.name, arg);
657
+ } else if (param.defaultExpression) {
658
+ bindings.set(param.name, substituteParams(cloneNode(param.defaultExpression), bindings));
659
+ } else {
660
+ bindings.set(param.name, undefinedIdentifier());
661
+ }
662
+ }
663
+ return bindings;
664
+ }
665
+ function statementHelperCall(node, names) {
666
+ if (node.type !== "ExpressionStatement") return void 0;
667
+ const expression = node.expression;
668
+ if (expression?.type !== "CallExpression" || expression.callee?.type !== "Identifier") {
669
+ return void 0;
670
+ }
671
+ return names.has(expression.callee.name) ? expression : void 0;
672
+ }
572
673
  function safelyDroppable(program, candidates) {
573
674
  const names = new Set(candidates.keys());
574
675
  const totalIds = /* @__PURE__ */ new Map();
575
676
  const stmtCalls = /* @__PURE__ */ new Map();
677
+ const unbindable = /* @__PURE__ */ new Set();
576
678
  walkNodes(program, (n) => {
577
679
  if (n.type === "Identifier" && names.has(n.name)) bump(totalIds, n.name);
578
- const e = n.type === "ExpressionStatement" ? n.expression : void 0;
579
- if (e?.type === "CallExpression" && e.callee?.type === "Identifier" && names.has(e.callee.name)) {
580
- bump(stmtCalls, e.callee.name);
581
- }
680
+ const call = statementHelperCall(n, names);
681
+ if (!call) return;
682
+ bump(stmtCalls, call.callee.name);
683
+ const fn = candidates.get(call.callee.name);
684
+ const params = fn && supportedParams(fn);
685
+ if (!params || !resolveHelperBindings(call, params)) unbindable.add(call.callee.name);
582
686
  });
583
687
  const safe = /* @__PURE__ */ new Map();
584
688
  for (const [name, fn] of candidates) {
585
- if ((totalIds.get(name) ?? 0) === 1 + (stmtCalls.get(name) ?? 0)) safe.set(name, fn);
689
+ if (!unbindable.has(name) && (totalIds.get(name) ?? 0) === 1 + (stmtCalls.get(name) ?? 0)) {
690
+ safe.set(name, fn);
691
+ }
586
692
  }
587
693
  return safe;
588
694
  }
@@ -625,11 +731,11 @@ function expandBody(bodyStmts, bindings, prov, ctx) {
625
731
  }
626
732
  function inlineHelper(call, ctx) {
627
733
  const fn = ctx.helpers.get(call.callee.name);
628
- const bindings = /* @__PURE__ */ new Map();
629
- (fn.params ?? []).forEach((p, i) => {
630
- const arg = call.arguments?.[i];
631
- if (arg) bindings.set(p.name, arg);
632
- });
734
+ if (!fn) return null;
735
+ const params = supportedParams(fn);
736
+ if (!params) return null;
737
+ const bindings = resolveHelperBindings(call, params);
738
+ if (!bindings) return null;
633
739
  const prov = {
634
740
  kind: "helper",
635
741
  fn: call.callee.name,