@barefootjs/rust 0.18.4 → 0.18.7

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/build.js CHANGED
@@ -187308,7 +187308,13 @@ import {
187308
187308
  prepareLoweringMatchers,
187309
187309
  queryHrefArgs,
187310
187310
  isValidHelperId,
187311
- sortComparatorFromArrow as sortComparatorFromArrow2
187311
+ sortComparatorFromArrow as sortComparatorFromArrow2,
187312
+ isDangerousInnerHtmlAttr,
187313
+ resolveDangerousInnerHtml,
187314
+ dangerousInnerHtmlMetacharViolation,
187315
+ dangerousInnerHtmlDiagnostic,
187316
+ resolveStaticLoopSource,
187317
+ collectLoopBoundNames
187312
187318
  } from "@barefootjs/jsx";
187313
187319
 
187314
187320
  // src/adapter/boolean-result.ts
@@ -187369,7 +187375,7 @@ function isAriaBooleanAttr(name) {
187369
187375
  }
187370
187376
 
187371
187377
  // src/adapter/minijinja-adapter.ts
187372
- import { BF_SLOT, BF_COND, BF_REGION } from "@barefootjs/shared";
187378
+ import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from "@barefootjs/shared";
187373
187379
 
187374
187380
  // src/adapter/lib/constants.ts
187375
187381
  var JINJA_TEMPLATE_PRIMITIVES = {
@@ -187378,7 +187384,10 @@ var JINJA_TEMPLATE_PRIMITIVES = {
187378
187384
  Number: { arity: 1, emit: (args) => `bf.number(${args[0]})` },
187379
187385
  "Math.floor": { arity: 1, emit: (args) => `bf.floor(${args[0]})` },
187380
187386
  "Math.ceil": { arity: 1, emit: (args) => `bf.ceil(${args[0]})` },
187381
- "Math.round": { arity: 1, emit: (args) => `bf.round(${args[0]})` }
187387
+ "Math.round": { arity: 1, emit: (args) => `bf.round(${args[0]})` },
187388
+ "Math.min": { arity: 2, emit: (args) => `bf.min(${args[0]}, ${args[1]})` },
187389
+ "Math.max": { arity: 2, emit: (args) => `bf.max(${args[0]}, ${args[1]})` },
187390
+ "Math.abs": { arity: 1, emit: (args) => `bf.abs(${args[0]})` }
187382
187391
  };
187383
187392
  var JINJA_PRIMITIVE_EMIT_MAP = Object.fromEntries(Object.entries(JINJA_TEMPLATE_PRIMITIVES).map(([k, v]) => [k, v.emit]));
187384
187393
 
@@ -187544,6 +187553,12 @@ function renderArrayMethod(method, object, args, emit) {
187544
187553
  const recv = emit(object);
187545
187554
  return `bf.trim(${recv})`;
187546
187555
  }
187556
+ case "trimStart":
187557
+ case "trimEnd": {
187558
+ const fn = method === "trimStart" ? "trim_start" : "trim_end";
187559
+ const recv = emit(object);
187560
+ return `bf.${fn}(${recv})`;
187561
+ }
187547
187562
  case "toFixed": {
187548
187563
  const recv = emit(object);
187549
187564
  const digits = args.length >= 1 ? emit(args[0]) : "0";
@@ -187577,6 +187592,12 @@ function renderArrayMethod(method, object, args, emit) {
187577
187592
  const newS = emit(args[1]);
187578
187593
  return `bf.replace(${recv}, ${oldS}, ${newS})`;
187579
187594
  }
187595
+ case "replaceAll": {
187596
+ const recv = emit(object);
187597
+ const oldS = emit(args[0]);
187598
+ const newS = emit(args[1]);
187599
+ return `bf.replace_all(${recv}, ${oldS}, ${newS})`;
187600
+ }
187580
187601
  case "repeat": {
187581
187602
  const recv = emit(object);
187582
187603
  const count = args.length === 0 ? "0" : emit(args[0]);
@@ -187671,6 +187692,39 @@ function renderFlatMethod(recv, depth, emit) {
187671
187692
  return `bf.flat(${recv}, ${d})`;
187672
187693
  }
187673
187694
 
187695
+ // src/adapter/lib/static-value.ts
187696
+ function staticValueToMinijinja(value) {
187697
+ if (value === null || value === undefined)
187698
+ return "none";
187699
+ if (typeof value === "boolean")
187700
+ return value ? "true" : "false";
187701
+ if (typeof value === "number")
187702
+ return String(value);
187703
+ if (typeof value === "string")
187704
+ return `'${escapeMinijinjaSingleQuoted(value)}'`;
187705
+ if (Array.isArray(value)) {
187706
+ const items = [];
187707
+ for (const el of value) {
187708
+ const serialized = staticValueToMinijinja(el);
187709
+ if (serialized === null)
187710
+ return null;
187711
+ items.push(serialized);
187712
+ }
187713
+ return `[${items.join(", ")}]`;
187714
+ }
187715
+ if (typeof value === "object") {
187716
+ const entries = [];
187717
+ for (const [key, val] of Object.entries(value)) {
187718
+ const serialized = staticValueToMinijinja(val);
187719
+ if (serialized === null)
187720
+ return null;
187721
+ entries.push(`${minijinjaHashKey(key)}: ${serialized}`);
187722
+ }
187723
+ return `{${entries.join(", ")}}`;
187724
+ }
187725
+ return null;
187726
+ }
187727
+
187674
187728
  // src/adapter/expr/emitters.ts
187675
187729
  import {
187676
187730
  groupBinaryOperand,
@@ -187719,7 +187773,7 @@ class JinjaFilterEmitter {
187719
187773
  return "none";
187720
187774
  return String(value);
187721
187775
  }
187722
- member(object, property, _computed, emit) {
187776
+ member(object, property, _computed, _optional, emit) {
187723
187777
  if (property === "length") {
187724
187778
  return `bf.length(${emit(object)})`;
187725
187779
  }
@@ -187825,7 +187879,7 @@ class JinjaTopLevelEmitter {
187825
187879
  return "none";
187826
187880
  return String(value);
187827
187881
  }
187828
- member(object, property, _computed, emit) {
187882
+ member(object, property, _computed, _optional, emit) {
187829
187883
  if (object.kind === "identifier" && object.name === "props") {
187830
187884
  return minijinjaIdent(property);
187831
187885
  }
@@ -188252,6 +188306,7 @@ class MinijinjaAdapter extends BaseAdapter {
188252
188306
  options;
188253
188307
  errors = [];
188254
188308
  inLoop = false;
188309
+ currentLoopKeyDepth = 0;
188255
188310
  propsObjectName = null;
188256
188311
  propsParams = [];
188257
188312
  booleanTypedProps = new Set;
@@ -188260,6 +188315,7 @@ class MinijinjaAdapter extends BaseAdapter {
188260
188315
  _searchParamsLocals = new Set;
188261
188316
  _loweringMatchers = [];
188262
188317
  localConstants = [];
188318
+ staticLoopSourceBoundNames = new Set;
188263
188319
  nullableOptionalProps = new Set;
188264
188320
  constructor(options = {}) {
188265
188321
  super();
@@ -188275,6 +188331,7 @@ class MinijinjaAdapter extends BaseAdapter {
188275
188331
  this.propsParams = ir.metadata.propsParams.map((p) => ({ name: p.name }));
188276
188332
  this.booleanTypedProps = collectBooleanTypedProps(ir);
188277
188333
  this.localConstants = ir.metadata.localConstants ?? [];
188334
+ this.staticLoopSourceBoundNames = collectLoopBoundNames(ir);
188278
188335
  this.nullableOptionalProps = collectNullableOptionalProps(ir);
188279
188336
  this.stringValueNames = collectStringValueNames(ir);
188280
188337
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants);
@@ -188328,7 +188385,7 @@ class MinijinjaAdapter extends BaseAdapter {
188328
188385
  return this.renderElement(node);
188329
188386
  }
188330
188387
  emitText(node) {
188331
- return node.value;
188388
+ return escapeHtml(node.value);
188332
188389
  }
188333
188390
  emitExpression(node) {
188334
188391
  return this.renderExpression(node);
@@ -188396,7 +188453,8 @@ class MinijinjaAdapter extends BaseAdapter {
188396
188453
  renderElement(element) {
188397
188454
  const tag = element.tag;
188398
188455
  const attrs = this.renderAttributes(element);
188399
- const children = this.renderChildren(element.children);
188456
+ const dangerousHtml = this.renderDangerousInnerHtml(element);
188457
+ const children = dangerousHtml !== null ? dangerousHtml : this.renderChildren(element.children);
188400
188458
  let hydrationAttrs = "";
188401
188459
  if (element.needsScope) {
188402
188460
  hydrationAttrs += ` ${this.renderScopeMarker("")}`;
@@ -188431,6 +188489,22 @@ class MinijinjaAdapter extends BaseAdapter {
188431
188489
  }
188432
188490
  return `<${tag}${attrs}${hydrationAttrs}>${children}</${tag}>`;
188433
188491
  }
188492
+ renderDangerousInnerHtml(element) {
188493
+ const resolution = resolveDangerousInnerHtml(element);
188494
+ if (!resolution)
188495
+ return null;
188496
+ if (resolution.kind === "dynamic") {
188497
+ this.errors.push(dangerousInnerHtmlDiagnostic(resolution.expr, resolution.loc));
188498
+ return "";
188499
+ }
188500
+ const violation = dangerousInnerHtmlMetacharViolation(resolution.html, this.name);
188501
+ if (violation) {
188502
+ const attr = element.attrs.find(isDangerousInnerHtmlAttr);
188503
+ this.errors.push(dangerousInnerHtmlDiagnostic(`{ __html: ${JSON.stringify(resolution.html)} }`, attr.loc, violation));
188504
+ return "";
188505
+ }
188506
+ return resolution.html;
188507
+ }
188434
188508
  renderExpression(expr) {
188435
188509
  if (expr.clientOnly) {
188436
188510
  if (expr.slotId) {
@@ -188438,7 +188512,7 @@ class MinijinjaAdapter extends BaseAdapter {
188438
188512
  }
188439
188513
  return "";
188440
188514
  }
188441
- const jinjaExpr = `bf.string(${this.convertExpressionToJinja(expr.expr)})`;
188515
+ const jinjaExpr = `bf.string(${this.convertExpressionToJinja(expr.expr, expr.parsed)})`;
188442
188516
  if (expr.slotId) {
188443
188517
  return `{{ bf.text_start("${expr.slotId}") | safe }}{{ ${jinjaExpr} }}{{ bf.text_end() | safe }}`;
188444
188518
  }
@@ -188529,8 +188603,12 @@ ${whenTrue}
188529
188603
  }
188530
188604
  });
188531
188605
  }
188606
+ const staticItems = resolveStaticLoopSource(loop.arrayParsed, this.localConstants, {
188607
+ isNameShadowed: (name) => this.staticLoopSourceBoundNames.has(name)
188608
+ });
188609
+ const staticArray = staticItems !== null ? staticValueToMinijinja(staticItems) : null;
188532
188610
  const arrayName = loop.array.trim();
188533
- if (/^[A-Za-z_$][\w$]*$/.test(arrayName)) {
188611
+ if (staticArray === null && /^[A-Za-z_$][\w$]*$/.test(arrayName)) {
188534
188612
  const arrayConst = (this.localConstants ?? []).find((c) => c.name === arrayName);
188535
188613
  if (arrayConst && !arrayConst.isModule && this._resolveLiteralConst(arrayName) === null) {
188536
188614
  this.errors.push({
@@ -188544,7 +188622,7 @@ ${whenTrue}
188544
188622
  });
188545
188623
  }
188546
188624
  }
188547
- const rawArray = this.convertExpressionToJinja(loop.array);
188625
+ const rawArray = staticArray ?? this.convertExpressionToJinja(loop.array);
188548
188626
  let array = rawArray;
188549
188627
  if (loop.sortComparator) {
188550
188628
  const sort = loop.sortComparator;
@@ -188558,7 +188636,7 @@ ${whenTrue}
188558
188636
  const renderedChildren = this.renderChildren(loop.children);
188559
188637
  const loopVar = loop.iterationShape === "keys" ? "__bf_item" : supportableDestructure ? "__bf_item" : param;
188560
188638
  const indexLocalLines = [];
188561
- if (loop.iterationShape === "keys") {
188639
+ if (loop.objectIteration) {} else if (loop.iterationShape === "keys") {
188562
188640
  indexLocalLines.push(`{% set ${minijinjaIdent(param)} = loop.index0 %}`);
188563
188641
  } else if (loop.index) {
188564
188642
  indexLocalLines.push(`{% set ${minijinjaIdent(loop.index)} = loop.index0 %}`);
@@ -188578,13 +188656,17 @@ ${whenTrue}
188578
188656
  }
188579
188657
  const prevInLoop = this.inLoop;
188580
188658
  this.inLoop = true;
188659
+ const prevLoopKeyDepth = this.currentLoopKeyDepth;
188660
+ this.currentLoopKeyDepth = loop.depth;
188581
188661
  const childrenUnderLoop = this.renderChildren(loop.children);
188662
+ this.currentLoopKeyDepth = prevLoopKeyDepth;
188582
188663
  this.inLoop = prevInLoop;
188583
188664
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{{ bf.comment("loop-i:" ~ bf.string(${this.convertExpressionToJinja(loop.key)})) | safe }}
188584
188665
  ${childrenUnderLoop}` : childrenUnderLoop;
188585
188666
  const lines = [];
188586
188667
  lines.push(`{{ bf.comment("loop:${loop.markerId}") | safe }}`);
188587
- lines.push(`{% for ${minijinjaIdent(loopVar)} in ${array} %}`);
188668
+ const forHeader = loop.objectIteration === "entries" ? `{% for ${minijinjaIdent(loop.index ?? param)}, ${minijinjaIdent(param)} in ${array}|items %}` : loop.objectIteration === "keys" ? `{% for ${minijinjaIdent(param)}, __bf_v in ${array}|items %}` : loop.objectIteration === "values" ? `{% for __bf_k, ${minijinjaIdent(param)} in ${array}|items %}` : `{% for ${minijinjaIdent(loopVar)} in ${array} %}`;
188669
+ lines.push(forHeader);
188588
188670
  for (const il of indexLocalLines)
188589
188671
  lines.push(il);
188590
188672
  if (loop.filterPredicate) {
@@ -188656,9 +188738,20 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188656
188738
  renderComponent(comp) {
188657
188739
  const segments = [{ kind: "entries", parts: [] }];
188658
188740
  const currentEntries = () => this.componentPropSegmentEntries(segments);
188741
+ const namedSlotSetBlocks = [];
188659
188742
  for (const p of comp.props) {
188660
188743
  if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
188661
188744
  continue;
188745
+ if (p.value.kind === "jsx-children" && p.name !== "children") {
188746
+ const prevInLoop = this.inLoop;
188747
+ this.inLoop = false;
188748
+ const slotBody = this.renderChildren(p.value.children);
188749
+ this.inLoop = prevInLoop;
188750
+ const captureName = `bf_prop_${this.childrenCaptureCounter++}`;
188751
+ namedSlotSetBlocks.push(`{% set ${captureName} %}${slotBody}{% endset %}`);
188752
+ currentEntries().push(`${minijinjaHashKey(p.name)}: ${captureName}`);
188753
+ continue;
188754
+ }
188662
188755
  if (p.value.kind === "spread") {
188663
188756
  const trimmed = p.value.expr.trim();
188664
188757
  if (this.propsObjectName && this.propsObjectName === trimmed) {
@@ -188687,11 +188780,11 @@ ${childrenUnderLoop}` : childrenUnderLoop;
188687
188780
  const captureName = `bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`;
188688
188781
  currentEntries().push(`${minijinjaHashKey("children")}: ${captureName}`);
188689
188782
  const dict = this.combineComponentPropSegments(segments);
188690
- return `{% set ${captureName} %}${childrenBody}{% endset %}{{ bf.render_child('${tplName}', ${dict}) | safe }}`;
188783
+ return `${namedSlotSetBlocks.join("")}{% set ${captureName} %}${childrenBody}{% endset %}{{ bf.render_child('${tplName}', ${dict}) | safe }}`;
188691
188784
  }
188692
188785
  const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
188693
188786
  const dictEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
188694
- return `{{ bf.render_child('${tplName}'${dictEntries}) | safe }}`;
188787
+ return `${namedSlotSetBlocks.join("")}{{ bf.render_child('${tplName}'${dictEntries}) | safe }}`;
188695
188788
  }
188696
188789
  childrenCaptureCounter = 0;
188697
188790
  presenceVarCounter = 0;
@@ -188736,7 +188829,7 @@ ${alternate}
188736
188829
  ${children}`;
188737
188830
  }
188738
188831
  elementAttrEmitter = {
188739
- emitLiteral: (value, name) => `${name}="${value.value}"`,
188832
+ emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
188740
188833
  emitExpression: (value, name) => {
188741
188834
  if (name === "style") {
188742
188835
  const css = this.tryLowerStyleObject(value.expr);
@@ -188841,12 +188934,15 @@ ${name}="{{ bf.string(${val}) }}"
188841
188934
  for (const attr of element.attrs) {
188842
188935
  if (attr.clientOnly)
188843
188936
  continue;
188937
+ if (isDangerousInnerHtmlAttr(attr))
188938
+ continue;
188844
188939
  let attrName;
188845
188940
  if (attr.name === "className")
188846
188941
  attrName = "class";
188847
- else if (attr.name === "key")
188848
- attrName = "data-key";
188849
- else
188942
+ else if (attr.name === "key") {
188943
+ const depth = this.currentLoopKeyDepth;
188944
+ attrName = depth > 0 ? `data-key-${depth}` : "data-key";
188945
+ } else
188850
188946
  attrName = attr.name;
188851
188947
  const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName);
188852
188948
  if (lowered)
@@ -189039,6 +189135,8 @@ Options:
189039
189135
  return isBooleanResultExpr(expr) || isAriaBooleanAttr(name) || this.isBooleanTypedPropRef(expr);
189040
189136
  }
189041
189137
  _resolveLiteralConst(name) {
189138
+ if (this.staticLoopSourceBoundNames.has(name))
189139
+ return null;
189042
189140
  const c = (this.localConstants ?? []).find((lc) => lc.name === name);
189043
189141
  if (c?.value === undefined)
189044
189142
  return null;
@@ -189051,6 +189149,8 @@ Options:
189051
189149
  return null;
189052
189150
  }
189053
189151
  _resolveStaticRecordLiteral(objectName, key) {
189152
+ if (this.staticLoopSourceBoundNames.has(objectName))
189153
+ return null;
189054
189154
  const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants);
189055
189155
  if (!hit)
189056
189156
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eAkG7B,CAAA"}
1
+ {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eA4F7B,CAAA"}