@barefootjs/test 0.21.3 → 0.23.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.
Files changed (2) hide show
  1. package/dist/index.js +649 -71
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -189221,18 +189221,39 @@ function createTemplateAwareStringProtector() {
189221
189221
  stash.push(s);
189222
189222
  return `__STRLIT_${i2}__`;
189223
189223
  };
189224
+ const STRING_LIT_RE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g;
189224
189225
  const protect = (s) => {
189225
189226
  s = s.replace(/`([^`]*)`/g, (_full, inner) => {
189226
189227
  const parts = splitTemplateInterpolations(inner);
189227
189228
  return "`" + parts.map((p) => p.startsWith("${") ? p : save(p)).join("") + "`";
189228
189229
  });
189229
- s = s.replace(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, (m) => save(m));
189230
+ s = s.replace(STRING_LIT_RE, (m) => save(m));
189230
189231
  return s;
189231
189232
  };
189232
189233
  const restore = (s) => {
189233
189234
  return s.replace(/__STRLIT_(\d+)__/g, (_, i2) => stash[Number(i2)]);
189234
189235
  };
189235
- return { protect, restore };
189236
+ const replaceProtectedCall = (haystack, needle, replacement) => {
189237
+ const escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
189238
+ const litValues = [];
189239
+ let pattern = "";
189240
+ let last = 0;
189241
+ for (const m of needle.matchAll(STRING_LIT_RE)) {
189242
+ pattern += escape(needle.slice(last, m.index));
189243
+ pattern += "__STRLIT_(\\d+)__";
189244
+ litValues.push(m[0]);
189245
+ last = m.index + m[0].length;
189246
+ }
189247
+ pattern += escape(needle.slice(last));
189248
+ for (const m of haystack.matchAll(new RegExp(pattern, "g"))) {
189249
+ const verified = m.slice(1).every((idx, i2) => stash[Number(idx)] === litValues[i2]);
189250
+ if (!verified)
189251
+ continue;
189252
+ return haystack.slice(0, m.index) + replacement() + haystack.slice(m.index + m[0].length);
189253
+ }
189254
+ return haystack;
189255
+ };
189256
+ return { protect, restore, replaceProtectedCall };
189236
189257
  }
189237
189258
  var VOID_ELEMENTS = new Set([
189238
189259
  "area",
@@ -189551,6 +189572,9 @@ function createAnalyzerContext(sourceFile, filePath) {
189551
189572
  jsxFunctions: new Map,
189552
189573
  jsxMultiReturnFunctions: new Map,
189553
189574
  reactiveFactories: new Map,
189575
+ declinedReactiveFactories: new Map,
189576
+ reactiveShapedHelpers: new Set,
189577
+ cleanFactoryImports: new Set,
189554
189578
  signalTupleRefs: new Map,
189555
189579
  propsType: null,
189556
189580
  propsParams: [],
@@ -189739,7 +189763,9 @@ var ErrorCodes = {
189739
189763
  STAGE_INIT_LOCAL_IN_TEMPLATE: "BF061",
189740
189764
  STAGE_AWAIT_IN_TEMPLATE: "BF062",
189741
189765
  INLINE_JSX_CALLBACK_CAPTURE: "BF080",
189742
- UNRECOGNIZED_REACTIVE_FACTORY: "BF110"
189766
+ UNRECOGNIZED_REACTIVE_FACTORY: "BF110",
189767
+ REACTIVE_FACTORY_RENAME_UNSUPPORTED: "BF111",
189768
+ REACTIVE_FACTORY_MODULE_CAPTURE: "BF112"
189743
189769
  };
189744
189770
  var errorMessages = {
189745
189771
  [ErrorCodes.MISSING_USE_CLIENT]: "'use client' directive required for components with createSignal or event handlers",
@@ -189763,7 +189789,9 @@ var errorMessages = {
189763
189789
  [ErrorCodes.STAGE_INIT_LOCAL_IN_TEMPLATE]: "Init-scope local referenced from template scope. The template lambda runs at module scope (via render() / renderChild()) and cannot reach init-body locals. Wrap the JSX expression in /* @client */, or lift the value to a prop or module-scope const.",
189764
189790
  [ErrorCodes.STAGE_AWAIT_IN_TEMPLATE]: "AwaitExpression in template scope. The generated template and init functions are synchronous — a bare `await` produces a SyntaxError at parse time. Move the await into the component body (before the return) or into an onMount/effect callback, and pass the resolved value to JSX.",
189765
189791
  [ErrorCodes.INLINE_JSX_CALLBACK_CAPTURE]: "Inline JSX-returning arrow function captures a non-module identifier. Extract the callback into a top-level 'use client' component (e.g. `function MyNode(n) { return <div/> }` then `renderNode={MyNode}`) or pass captured values via component props.",
189766
- [ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY]: "Tuple destructuring of a non-reactive factory call. The compiler only recognizes createSignal / createMemo calls and same-file helpers that wrap them with a single `return [a, b]` exit."
189792
+ [ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY]: "Tuple destructuring of a non-reactive factory call. The compiler only recognizes createSignal / createMemo calls and same-file helpers that wrap them with a single `return [a, b]` exit.",
189793
+ [ErrorCodes.REACTIVE_FACTORY_RENAME_UNSUPPORTED]: "Reactive factory object return/destructure must use shorthand properties only. " + "Property renames (`{ lists: myLists }`), defaults, and rest elements are not " + "supported — destructure with the factory's own property names.",
189794
+ [ErrorCodes.REACTIVE_FACTORY_MODULE_CAPTURE]: "Imported reactive factory references bindings from its own module scope, so its " + "body cannot be inlined into the component file. Move those helpers into the " + "component file, pass them to the factory as parameters, or define the factory " + "in the component file."
189767
189795
  };
189768
189796
  function createError(code2, loc, options) {
189769
189797
  if (code2 === undefined || !(code2 in errorMessages)) {
@@ -190032,6 +190060,10 @@ function analyzeComponent(source, filePath, targetComponentName, program) {
190032
190060
  }
190033
190061
  const ctx = createAnalyzerContext(sourceFile, filePath);
190034
190062
  ctx.checker = checker;
190063
+ ctx.reactiveFactories = prescan.factories;
190064
+ ctx.declinedReactiveFactories = prescan.declined;
190065
+ ctx.reactiveShapedHelpers = prescan.reactiveShaped;
190066
+ ctx.cleanFactoryImports = prescan.cleanFactoryImports;
190035
190067
  const brandImportLoc = findBrandPackageImportLoc(sourceFile, filePath);
190036
190068
  if (!hadSharedProgram && brandImportLoc !== null) {
190037
190069
  ctx.errors.push(createError(ErrorCodes.SHARED_PROGRAM_REQUIRED, brandImportLoc));
@@ -190937,6 +190969,7 @@ var CLIENT_EXPORTS = new Set([
190937
190969
  "cleanupPortalPlaceholder",
190938
190970
  "createSearchParams",
190939
190971
  "queryHref",
190972
+ "formatDate",
190940
190973
  "Async",
190941
190974
  "Region"
190942
190975
  ]);
@@ -192164,27 +192197,241 @@ var REACTIVE_PRIMITIVES = new Set([
192164
192197
  function prescanReactiveFactoriesInSource(source, filePath) {
192165
192198
  const sourceFile = import_typescript8.default.createSourceFile(filePath + ".prescan", source, import_typescript8.default.ScriptTarget.Latest, true, import_typescript8.default.ScriptKind.TSX);
192166
192199
  const factories = new Map;
192200
+ const declined = new Map;
192201
+ const reactiveShaped = new Set;
192202
+ const cleanFactoryImports = new Set;
192167
192203
  function visitTop(node) {
192168
192204
  if (import_typescript8.default.isFunctionDeclaration(node) && node.name && node.body) {
192169
- const info = detectReactiveFactory(node, sourceFile, filePath);
192170
- if (info)
192171
- factories.set(node.name.text, info);
192205
+ const det = detectReactiveFactory(node, sourceFile, filePath);
192206
+ if (!det)
192207
+ return;
192208
+ switch (det.kind) {
192209
+ case "factory":
192210
+ factories.set(node.name.text, det.info);
192211
+ break;
192212
+ case "declined":
192213
+ declined.set(node.name.text, det.declined);
192214
+ break;
192215
+ case "reactive-shaped":
192216
+ reactiveShaped.add(node.name.text);
192217
+ break;
192218
+ }
192172
192219
  }
192173
192220
  }
192174
192221
  import_typescript8.default.forEachChild(sourceFile, visitTop);
192175
- return { factories, sourceFile };
192222
+ const result = { factories, declined, reactiveShaped, cleanFactoryImports, sourceFile };
192223
+ prescanImportedReactiveFactories(sourceFile, filePath, result);
192224
+ return result;
192225
+ }
192226
+ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
192227
+ const candidateCallees = new Set;
192228
+ function collectCandidates(node) {
192229
+ if (import_typescript8.default.isVariableDeclaration(node) && (import_typescript8.default.isArrayBindingPattern(node.name) || import_typescript8.default.isObjectBindingPattern(node.name)) && node.initializer && import_typescript8.default.isCallExpression(node.initializer) && import_typescript8.default.isIdentifier(node.initializer.expression)) {
192230
+ candidateCallees.add(node.initializer.expression.text);
192231
+ }
192232
+ import_typescript8.default.forEachChild(node, collectCandidates);
192233
+ }
192234
+ collectCandidates(entrySourceFile);
192235
+ if (candidateCallees.size === 0)
192236
+ return;
192237
+ const importsToCheck = [];
192238
+ for (const stmt of entrySourceFile.statements) {
192239
+ if (!import_typescript8.default.isImportDeclaration(stmt))
192240
+ continue;
192241
+ if (!import_typescript8.default.isStringLiteral(stmt.moduleSpecifier))
192242
+ continue;
192243
+ const src = stmt.moduleSpecifier.text;
192244
+ if (!src.startsWith("./") && !src.startsWith("../"))
192245
+ continue;
192246
+ if (stmt.importClause?.isTypeOnly)
192247
+ continue;
192248
+ const namedBindings = stmt.importClause?.namedBindings;
192249
+ if (!namedBindings || !import_typescript8.default.isNamedImports(namedBindings))
192250
+ continue;
192251
+ const specs = [];
192252
+ for (const el of namedBindings.elements) {
192253
+ if (el.isTypeOnly)
192254
+ continue;
192255
+ const local = el.name.text;
192256
+ if (!candidateCallees.has(local))
192257
+ continue;
192258
+ specs.push({ exported: (el.propertyName ?? el.name).text, local });
192259
+ }
192260
+ if (specs.length === 0)
192261
+ continue;
192262
+ importsToCheck.push({ src, specs });
192263
+ }
192264
+ if (importsToCheck.length === 0)
192265
+ return;
192266
+ for (const { src, specs } of importsToCheck) {
192267
+ const resolved = resolveRelativeImportToFile(src, filePath);
192268
+ if (!resolved)
192269
+ continue;
192270
+ let content;
192271
+ try {
192272
+ content = fs.readFileSync(resolved, "utf8");
192273
+ } catch {
192274
+ continue;
192275
+ }
192276
+ const alreadyKnown = (name) => result.factories.has(name) || result.declined.has(name) || result.reactiveShaped.has(name);
192277
+ const hasAnyPrimitiveText = [...REACTIVE_PRIMITIVES].some((p) => content.includes(p));
192278
+ if (!hasAnyPrimitiveText) {
192279
+ for (const spec of specs) {
192280
+ if (!alreadyKnown(spec.local))
192281
+ result.cleanFactoryImports.add(spec.local);
192282
+ }
192283
+ continue;
192284
+ }
192285
+ const helperSf = import_typescript8.default.createSourceFile(resolved + ".prescan", content, import_typescript8.default.ScriptTarget.Latest, true, import_typescript8.default.ScriptKind.TSX);
192286
+ const localFns = new Map;
192287
+ const exportedFns = new Map;
192288
+ for (const stmt of helperSf.statements) {
192289
+ if (import_typescript8.default.isFunctionDeclaration(stmt) && stmt.name && stmt.body) {
192290
+ localFns.set(stmt.name.text, stmt);
192291
+ const hasExportModifier = stmt.modifiers?.some((m) => m.kind === import_typescript8.default.SyntaxKind.ExportKeyword) ?? false;
192292
+ const hasDefaultModifier = stmt.modifiers?.some((m) => m.kind === import_typescript8.default.SyntaxKind.DefaultKeyword) ?? false;
192293
+ if (hasExportModifier && !hasDefaultModifier) {
192294
+ exportedFns.set(stmt.name.text, stmt);
192295
+ }
192296
+ }
192297
+ }
192298
+ for (const stmt of helperSf.statements) {
192299
+ if (import_typescript8.default.isExportDeclaration(stmt) && stmt.exportClause && import_typescript8.default.isNamedExports(stmt.exportClause) && !stmt.moduleSpecifier && !stmt.isTypeOnly) {
192300
+ for (const el of stmt.exportClause.elements) {
192301
+ if (el.isTypeOnly)
192302
+ continue;
192303
+ const fn = localFns.get((el.propertyName ?? el.name).text);
192304
+ if (fn)
192305
+ exportedFns.set(el.name.text, fn);
192306
+ }
192307
+ }
192308
+ }
192309
+ const moduleBindings = collectHelperModuleValueBindings(helperSf);
192310
+ for (const spec of specs) {
192311
+ if (alreadyKnown(spec.local))
192312
+ continue;
192313
+ const fn = exportedFns.get(spec.exported);
192314
+ if (!fn) {
192315
+ result.cleanFactoryImports.add(spec.local);
192316
+ continue;
192317
+ }
192318
+ const det = detectReactiveFactory(fn, helperSf, resolved);
192319
+ if (!det) {
192320
+ result.cleanFactoryImports.add(spec.local);
192321
+ continue;
192322
+ }
192323
+ switch (det.kind) {
192324
+ case "reactive-shaped":
192325
+ result.reactiveShaped.add(spec.local);
192326
+ break;
192327
+ case "declined":
192328
+ result.declined.set(spec.local, det.declined);
192329
+ break;
192330
+ case "factory": {
192331
+ const offending = moduleCaptureCheck(fn, det.info, moduleBindings, fn.name.text);
192332
+ if (offending.length > 0) {
192333
+ result.declined.set(spec.local, {
192334
+ code: "BF112",
192335
+ detail: `'${offending.join("', '")}'`,
192336
+ loc: det.info.loc
192337
+ });
192338
+ } else {
192339
+ det.info.sourceFilePath = resolved;
192340
+ result.factories.set(spec.local, det.info);
192341
+ }
192342
+ break;
192343
+ }
192344
+ }
192345
+ }
192346
+ }
192347
+ }
192348
+ function collectHelperModuleValueBindings(sf) {
192349
+ const names = new Set;
192350
+ for (const stmt of sf.statements) {
192351
+ if (import_typescript8.default.isVariableStatement(stmt)) {
192352
+ const out = [];
192353
+ for (const decl of stmt.declarationList.declarations) {
192354
+ addBindingNames(decl.name, out);
192355
+ }
192356
+ for (const n of out)
192357
+ names.add(n);
192358
+ continue;
192359
+ }
192360
+ if ((import_typescript8.default.isFunctionDeclaration(stmt) || import_typescript8.default.isClassDeclaration(stmt) || import_typescript8.default.isEnumDeclaration(stmt)) && stmt.name) {
192361
+ names.add(stmt.name.text);
192362
+ continue;
192363
+ }
192364
+ if (import_typescript8.default.isImportDeclaration(stmt)) {
192365
+ if (stmt.importClause?.isTypeOnly)
192366
+ continue;
192367
+ if (!import_typescript8.default.isStringLiteral(stmt.moduleSpecifier))
192368
+ continue;
192369
+ const src = stmt.moduleSpecifier.text;
192370
+ if (src === "@barefootjs/client" || src === "@barefootjs/client/runtime")
192371
+ continue;
192372
+ if (stmt.importClause?.name)
192373
+ names.add(stmt.importClause.name.text);
192374
+ const namedBindings = stmt.importClause?.namedBindings;
192375
+ if (namedBindings && import_typescript8.default.isNamedImports(namedBindings)) {
192376
+ for (const el of namedBindings.elements) {
192377
+ if (el.isTypeOnly)
192378
+ continue;
192379
+ names.add(el.name.text);
192380
+ }
192381
+ }
192382
+ if (namedBindings && import_typescript8.default.isNamespaceImport(namedBindings)) {
192383
+ names.add(namedBindings.name.text);
192384
+ }
192385
+ }
192386
+ }
192387
+ return names;
192388
+ }
192389
+ function moduleCaptureCheck(fn, info, moduleBindings, selfName) {
192390
+ if (!fn.body)
192391
+ return [];
192392
+ const free = extractFreeIdentifiersFromNode(fn.body);
192393
+ const exclude = new Set(info.params);
192394
+ for (const b of info.localBindings)
192395
+ exclude.add(b);
192396
+ for (const r of info.returnTupleIdentifiers)
192397
+ exclude.add(r);
192398
+ for (const p of REACTIVE_PRIMITIVES)
192399
+ exclude.add(p);
192400
+ exclude.add(selfName);
192401
+ const offending = [];
192402
+ for (const id of free) {
192403
+ if (exclude.has(id))
192404
+ continue;
192405
+ if (moduleBindings.has(id))
192406
+ offending.push(id);
192407
+ }
192408
+ return offending.sort();
192176
192409
  }
192177
192410
  function detectReactiveFactory(node, sourceFile, filePath) {
192178
192411
  if (!node.body || !node.name)
192179
192412
  return null;
192180
- let tupleReturn = null;
192413
+ let hasReactiveCall = false;
192414
+ function checkForReactive(n) {
192415
+ if (hasReactiveCall)
192416
+ return;
192417
+ if (import_typescript8.default.isCallExpression(n) && import_typescript8.default.isIdentifier(n.expression) && REACTIVE_PRIMITIVES.has(n.expression.text)) {
192418
+ hasReactiveCall = true;
192419
+ return;
192420
+ }
192421
+ import_typescript8.default.forEachChild(n, checkForReactive);
192422
+ }
192423
+ checkForReactive(node.body);
192424
+ if (!hasReactiveCall)
192425
+ return null;
192426
+ const loc = getSourceLocation(node, sourceFile, filePath);
192427
+ let returnExpr = null;
192181
192428
  let returnCount = 0;
192182
192429
  for (const stmt of node.body.statements) {
192183
192430
  if (!import_typescript8.default.isReturnStatement(stmt))
192184
192431
  continue;
192185
192432
  returnCount++;
192186
192433
  if (!stmt.expression)
192187
- return null;
192434
+ return { kind: "reactive-shaped" };
192188
192435
  let expr = stmt.expression;
192189
192436
  while (import_typescript8.default.isParenthesizedExpression(expr))
192190
192437
  expr = expr.expression;
@@ -192192,33 +192439,42 @@ function detectReactiveFactory(node, sourceFile, filePath) {
192192
192439
  expr = expr.expression;
192193
192440
  if (import_typescript8.default.isTypeAssertionExpression(expr))
192194
192441
  expr = expr.expression;
192195
- if (!import_typescript8.default.isArrayLiteralExpression(expr))
192196
- return null;
192197
- tupleReturn = expr;
192442
+ returnExpr = expr;
192198
192443
  }
192199
- if (returnCount !== 1 || !tupleReturn)
192200
- return null;
192444
+ if (returnCount !== 1 || !returnExpr)
192445
+ return { kind: "reactive-shaped" };
192201
192446
  const returnTupleIdentifiers = [];
192202
- for (const el of tupleReturn.elements) {
192203
- if (!import_typescript8.default.isIdentifier(el))
192204
- return null;
192205
- returnTupleIdentifiers.push(el.text);
192206
- }
192207
- if (returnTupleIdentifiers.length === 0)
192208
- return null;
192209
- let hasReactiveCall = false;
192210
- function checkForReactive(n) {
192211
- if (hasReactiveCall)
192212
- return;
192213
- if (import_typescript8.default.isCallExpression(n) && import_typescript8.default.isIdentifier(n.expression) && REACTIVE_PRIMITIVES.has(n.expression.text)) {
192214
- hasReactiveCall = true;
192215
- return;
192447
+ let returnKind;
192448
+ if (import_typescript8.default.isArrayLiteralExpression(returnExpr)) {
192449
+ returnKind = "tuple";
192450
+ for (const el of returnExpr.elements) {
192451
+ if (!import_typescript8.default.isIdentifier(el))
192452
+ return { kind: "reactive-shaped" };
192453
+ returnTupleIdentifiers.push(el.text);
192454
+ }
192455
+ if (returnTupleIdentifiers.length === 0)
192456
+ return { kind: "reactive-shaped" };
192457
+ } else if (import_typescript8.default.isObjectLiteralExpression(returnExpr)) {
192458
+ returnKind = "object";
192459
+ const hasNonShorthand = returnExpr.properties.some((p) => !import_typescript8.default.isShorthandPropertyAssignment(p));
192460
+ if (hasNonShorthand) {
192461
+ return {
192462
+ kind: "declined",
192463
+ declined: {
192464
+ code: "BF111",
192465
+ detail: `return object of '${node.name.text}' uses non-shorthand properties`,
192466
+ loc
192467
+ }
192468
+ };
192216
192469
  }
192217
- import_typescript8.default.forEachChild(n, checkForReactive);
192470
+ for (const p of returnExpr.properties) {
192471
+ returnTupleIdentifiers.push(p.name.text);
192472
+ }
192473
+ if (returnTupleIdentifiers.length === 0)
192474
+ return { kind: "reactive-shaped" };
192475
+ } else {
192476
+ return { kind: "reactive-shaped" };
192218
192477
  }
192219
- checkForReactive(node.body);
192220
- if (!hasReactiveCall)
192221
- return null;
192222
192478
  const localBindings = [];
192223
192479
  for (const stmt of node.body.statements) {
192224
192480
  if (import_typescript8.default.isVariableStatement(stmt)) {
@@ -192231,19 +192487,24 @@ function detectReactiveFactory(node, sourceFile, filePath) {
192231
192487
  }
192232
192488
  const bodyStatements = node.body.statements.filter((s) => !import_typescript8.default.isReturnStatement(s)).map((s) => s.getText(sourceFile)).join(`
192233
192489
  `);
192234
- const params = node.parameters.map((p) => {
192235
- if (import_typescript8.default.isIdentifier(p.name))
192236
- return p.name.text;
192237
- return "";
192238
- });
192239
- if (params.some((p) => p === ""))
192240
- return null;
192490
+ const params = [];
192491
+ for (const p of node.parameters) {
192492
+ if (import_typescript8.default.isIdentifier(p.name)) {
192493
+ params.push(p.name.text);
192494
+ continue;
192495
+ }
192496
+ return { kind: "reactive-shaped" };
192497
+ }
192241
192498
  return {
192242
- params,
192243
- bodySource: bodyStatements,
192244
- returnTupleIdentifiers,
192245
- localBindings,
192246
- loc: getSourceLocation(node, sourceFile, filePath)
192499
+ kind: "factory",
192500
+ info: {
192501
+ params,
192502
+ bodySource: bodyStatements,
192503
+ returnTupleIdentifiers,
192504
+ returnKind,
192505
+ localBindings,
192506
+ loc
192507
+ }
192247
192508
  };
192248
192509
  }
192249
192510
  function addBindingNames(name, out) {
@@ -192281,8 +192542,6 @@ function rewriteFactoryCallsInSource(source, prescan) {
192281
192542
  });
192282
192543
  }
192283
192544
  function maybeRewriteDecl(stmt, decl) {
192284
- if (!import_typescript8.default.isArrayBindingPattern(decl.name))
192285
- return;
192286
192545
  if (!decl.initializer || !import_typescript8.default.isCallExpression(decl.initializer))
192287
192546
  return;
192288
192547
  if (!import_typescript8.default.isIdentifier(decl.initializer.expression))
@@ -192291,7 +192550,21 @@ function rewriteFactoryCallsInSource(source, prescan) {
192291
192550
  const factory = factories.get(factoryName);
192292
192551
  if (!factory)
192293
192552
  return;
192294
- const elements = decl.name.elements;
192553
+ if (import_typescript8.default.isArrayBindingPattern(decl.name)) {
192554
+ if (factory.returnKind !== "tuple")
192555
+ return;
192556
+ rewriteTupleDecl(stmt, decl.name, decl.initializer, factory);
192557
+ return;
192558
+ }
192559
+ if (import_typescript8.default.isObjectBindingPattern(decl.name)) {
192560
+ if (factory.returnKind !== "object")
192561
+ return;
192562
+ rewriteObjectDecl(stmt, decl.name, decl.initializer, factory);
192563
+ return;
192564
+ }
192565
+ }
192566
+ function rewriteTupleDecl(stmt, pattern, call, factory) {
192567
+ const elements = pattern.elements;
192295
192568
  if (elements.length !== factory.returnTupleIdentifiers.length)
192296
192569
  return;
192297
192570
  const callerNames = [];
@@ -192300,15 +192573,43 @@ function rewriteFactoryCallsInSource(source, prescan) {
192300
192573
  return;
192301
192574
  callerNames.push(el.name.text);
192302
192575
  }
192303
- const argTexts = decl.initializer.arguments.map((a) => a.getText(sourceFile));
192576
+ const excludeFromSuffixRename = new Set(factory.params);
192577
+ for (const r of factory.returnTupleIdentifiers)
192578
+ excludeFromSuffixRename.add(r);
192579
+ const renameReturnToCallerNames = new Map;
192580
+ for (let i2 = 0;i2 < factory.returnTupleIdentifiers.length; i2++) {
192581
+ renameReturnToCallerNames.set(factory.returnTupleIdentifiers[i2], callerNames[i2]);
192582
+ }
192583
+ inlineFactoryCallAtSite(stmt, factory, call.arguments, excludeFromSuffixRename, renameReturnToCallerNames);
192584
+ }
192585
+ function rewriteObjectDecl(stmt, pattern, call, factory) {
192586
+ const destructured = new Set;
192587
+ for (const el of pattern.elements) {
192588
+ if (el.dotDotDotToken)
192589
+ return;
192590
+ if (el.propertyName)
192591
+ return;
192592
+ if (el.initializer)
192593
+ return;
192594
+ if (!import_typescript8.default.isIdentifier(el.name))
192595
+ return;
192596
+ if (!factory.returnTupleIdentifiers.includes(el.name.text))
192597
+ return;
192598
+ destructured.add(el.name.text);
192599
+ }
192600
+ const excludeFromSuffixRename = new Set(factory.params);
192601
+ for (const d of destructured)
192602
+ excludeFromSuffixRename.add(d);
192603
+ inlineFactoryCallAtSite(stmt, factory, call.arguments, excludeFromSuffixRename, null);
192604
+ }
192605
+ function inlineFactoryCallAtSite(stmt, factory, args, excludeFromSuffixRename, renameReturnToCallerNames) {
192606
+ const argTexts = args.map((a) => a.getText(sourceFile));
192304
192607
  const thisCallIndex = callSiteIndex++;
192305
192608
  const suffix = `_bf${thisCallIndex}`;
192306
192609
  let body = factory.bodySource;
192307
192610
  const internalRenames = new Set(factory.localBindings);
192308
- for (const p of factory.params)
192309
- internalRenames.delete(p);
192310
- for (const r of factory.returnTupleIdentifiers)
192311
- internalRenames.delete(r);
192611
+ for (const ex of excludeFromSuffixRename)
192612
+ internalRenames.delete(ex);
192312
192613
  for (const name of internalRenames) {
192313
192614
  body = body.replace(new RegExp(`\\b${escapeRegex(name)}\\b`, "g"), name + suffix);
192314
192615
  }
@@ -192319,10 +192620,10 @@ function rewriteFactoryCallsInSource(source, prescan) {
192319
192620
  const wrapped = atomicArg.test(a.trim()) ? a.trim() : `(${a})`;
192320
192621
  body = body.replace(new RegExp(`\\b${escapeRegex(p)}\\b`, "g"), wrapped);
192321
192622
  }
192322
- for (let i2 = 0;i2 < factory.returnTupleIdentifiers.length; i2++) {
192323
- const n = factory.returnTupleIdentifiers[i2];
192324
- const caller = callerNames[i2];
192325
- body = body.replace(new RegExp(`\\b${escapeRegex(n)}\\b`, "g"), caller);
192623
+ if (renameReturnToCallerNames) {
192624
+ for (const [n, caller] of renameReturnToCallerNames) {
192625
+ body = body.replace(new RegExp(`\\b${escapeRegex(n)}\\b`, "g"), caller);
192626
+ }
192326
192627
  }
192327
192628
  edits.push({
192328
192629
  start: stmt.getStart(sourceFile),
@@ -192352,6 +192653,12 @@ function isPascalCaseComponentFn(node) {
192352
192653
  function escapeRegex(s) {
192353
192654
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
192354
192655
  }
192656
+ function declinedFactoryMessage(callee, d) {
192657
+ if (d.code === "BF112") {
192658
+ return `Reactive factory '${callee}' references ${d.detail} from its own module ` + `scope and cannot be inlined. Move the referenced helper(s) into this file, ` + `pass them as factory arguments, or inline the factory here.`;
192659
+ }
192660
+ return `Reactive factory '${callee}' cannot be inlined: ${d.detail}.`;
192661
+ }
192355
192662
  function validateReactiveFactoryCalls(ctx) {
192356
192663
  if (!ctx.componentNode)
192357
192664
  return;
@@ -192362,25 +192669,103 @@ function validateReactiveFactoryCalls(ctx) {
192362
192669
  if (!import_typescript8.default.isVariableStatement(stmt))
192363
192670
  continue;
192364
192671
  for (const decl of stmt.declarationList.declarations) {
192365
- if (!import_typescript8.default.isArrayBindingPattern(decl.name))
192366
- continue;
192367
192672
  if (!decl.initializer || !import_typescript8.default.isCallExpression(decl.initializer))
192368
192673
  continue;
192369
192674
  if (!import_typescript8.default.isIdentifier(decl.initializer.expression))
192370
192675
  continue;
192371
192676
  const callee = decl.initializer.expression.text;
192372
- if (callee === "createSignal" || callee === "createMemo")
192373
- continue;
192374
- if (resolveEnvSignalKey(decl.initializer, ctx))
192677
+ const loc = getSourceLocation(stmt, ctx.sourceFile, ctx.filePath);
192678
+ if (import_typescript8.default.isArrayBindingPattern(decl.name)) {
192679
+ if (callee === "createSignal" || callee === "createMemo")
192680
+ continue;
192681
+ if (resolveEnvSignalKey(decl.initializer, ctx))
192682
+ continue;
192683
+ const declinedEntry = ctx.declinedReactiveFactories.get(callee);
192684
+ if (declinedEntry) {
192685
+ ctx.errors.push(createError(declinedEntry.code === "BF112" ? ErrorCodes.REACTIVE_FACTORY_MODULE_CAPTURE : ErrorCodes.REACTIVE_FACTORY_RENAME_UNSUPPORTED, loc, { severity: "error", message: declinedFactoryMessage(callee, declinedEntry) }));
192686
+ continue;
192687
+ }
192688
+ const objectFactory = ctx.reactiveFactories.get(callee);
192689
+ if (objectFactory && objectFactory.returnKind === "object") {
192690
+ ctx.errors.push(createError(ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY, loc, {
192691
+ severity: "error",
192692
+ message: `'${callee}' is a reactive factory that returns an object — destructure ` + `it with a matching object pattern: const { ${objectFactory.returnTupleIdentifiers.join(", ")} } = ${callee}(...)`
192693
+ }));
192694
+ continue;
192695
+ }
192696
+ ctx.errors.push(createError(ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY, loc, {
192697
+ severity: "error",
192698
+ message: `Tuple destructuring of '${callee}(...)': this helper is not a ` + `recognised reactive factory (createSignal / createMemo / a ` + `same-file helper that wraps them with a single \`return [a, b, ...]\`).`,
192699
+ suggestion: {
192700
+ message: `Inline the createSignal call at the call site, or move the ` + `helper into this file as a function that returns a tuple of ` + `identifiers at its single exit point.`
192701
+ }
192702
+ }));
192375
192703
  continue;
192376
- ctx.errors.push(createError(ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY, getSourceLocation(stmt, ctx.sourceFile, ctx.filePath), {
192704
+ }
192705
+ if (import_typescript8.default.isObjectBindingPattern(decl.name)) {
192706
+ validateObjectFactoryDestructure(ctx, decl.name, callee, loc);
192707
+ }
192708
+ }
192709
+ }
192710
+ }
192711
+ function validateObjectFactoryDestructure(ctx, pattern, callee, loc) {
192712
+ const factory = ctx.reactiveFactories.get(callee);
192713
+ if (factory) {
192714
+ if (factory.returnKind === "tuple") {
192715
+ ctx.errors.push(createError(ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY, loc, {
192377
192716
  severity: "error",
192378
- message: `Tuple destructuring of '${callee}(...)': this helper is not a ` + `recognised reactive factory (createSignal / createMemo / a ` + `same-file helper that wraps them with a single \`return [a, b, ...]\`).`,
192379
- suggestion: {
192380
- message: `Inline the createSignal call at the call site, or move the ` + `helper into this file as a function that returns a tuple of ` + `identifiers at its single exit point.`
192381
- }
192717
+ message: `'${callee}' is a reactive factory that returns a tuple destructure ` + `it positionally: const [${factory.returnTupleIdentifiers.join(", ")}] = ${callee}(...)`
192718
+ }));
192719
+ return;
192720
+ }
192721
+ const hasUnsupportedElement = pattern.elements.some((el) => !!el.propertyName || !!el.initializer || !!el.dotDotDotToken || !import_typescript8.default.isIdentifier(el.name));
192722
+ if (hasUnsupportedElement) {
192723
+ ctx.errors.push(createError(ErrorCodes.REACTIVE_FACTORY_RENAME_UNSUPPORTED, loc, {
192724
+ severity: "error",
192725
+ message: `Object destructure of reactive factory '${callee}' uses a property ` + `rename, default, or rest element; only shorthand destructuring of ` + `{ ${factory.returnTupleIdentifiers.join(", ")} } is supported.`
192726
+ }));
192727
+ return;
192728
+ }
192729
+ const unknown = pattern.elements.map((el) => import_typescript8.default.isIdentifier(el.name) ? el.name.text : "").filter((name) => name && !factory.returnTupleIdentifiers.includes(name));
192730
+ if (unknown.length > 0) {
192731
+ const label = unknown.length === 1 ? "property" : "properties";
192732
+ ctx.errors.push(createError(ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY, loc, {
192733
+ severity: "error",
192734
+ message: `Object destructure of reactive factory '${callee}' references ${label} ` + `'${unknown.join("', '")}' not present in its return { ${factory.returnTupleIdentifiers.join(", ")} }.`
192382
192735
  }));
192736
+ return;
192383
192737
  }
192738
+ return;
192739
+ }
192740
+ const declinedEntry = ctx.declinedReactiveFactories.get(callee);
192741
+ if (declinedEntry) {
192742
+ ctx.errors.push(createError(declinedEntry.code === "BF112" ? ErrorCodes.REACTIVE_FACTORY_MODULE_CAPTURE : ErrorCodes.REACTIVE_FACTORY_RENAME_UNSUPPORTED, loc, { severity: "error", message: declinedFactoryMessage(callee, declinedEntry) }));
192743
+ return;
192744
+ }
192745
+ if (ctx.reactiveShapedHelpers.has(callee)) {
192746
+ ctx.errors.push(createError(ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY, loc, {
192747
+ severity: "error",
192748
+ message: `Object destructure of '${callee}(...)': this helper wraps a reactive ` + `primitive but does not match the inlinable factory shape (single ` + "`return { a, b }` of shorthand identifiers at its one exit point)."
192749
+ }));
192750
+ return;
192751
+ }
192752
+ if (ctx.cleanFactoryImports.has(callee))
192753
+ return;
192754
+ let matchedImportSource = null;
192755
+ for (const imp of ctx.imports) {
192756
+ if (imp.isTypeOnly)
192757
+ continue;
192758
+ const spec = imp.specifiers.find((s) => !s.isTypeOnly && (s.alias ?? s.name) === callee);
192759
+ if (spec) {
192760
+ matchedImportSource = imp.source;
192761
+ break;
192762
+ }
192763
+ }
192764
+ if (matchedImportSource !== null && !matchedImportSource.startsWith("@barefootjs/") && /^(use|create)[A-Z]/.test(callee)) {
192765
+ ctx.errors.push(createError(ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY, loc, {
192766
+ severity: "error",
192767
+ message: `Object destructure of imported '${callee}(...)': the compiler cannot ` + `inspect this import (non-relative or unresolvable path), so if it wraps ` + `createSignal/createMemo the destructured bindings will not be reactive. Move ` + `the helper to a relative-imported file or inline its body.`
192768
+ }));
192384
192769
  }
192385
192770
  }
192386
192771
 
@@ -192792,6 +193177,114 @@ function resolveFreeRefs(node, env) {
192792
193177
  return resolveFreeRefsInternal(node, env, new Set);
192793
193178
  }
192794
193179
 
193180
+ // ../jsx/src/to-locale-date-lowering.ts
193181
+ var TO_LOCALE_TZ_RE = /^(?:UTC|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
193182
+ var PROBE_UTC = new Date(Date.UTC(2001, 1, 3));
193183
+ var patternCache = new Map;
193184
+ function resolveLocaleDatePattern(locale) {
193185
+ const cached = patternCache.get(locale);
193186
+ if (cached !== undefined)
193187
+ return cached;
193188
+ const derived = derivePattern(locale);
193189
+ patternCache.set(locale, derived);
193190
+ return derived;
193191
+ }
193192
+ function derivePattern(locale) {
193193
+ let parts;
193194
+ try {
193195
+ const dtf = new Intl.DateTimeFormat(locale, { timeZone: "UTC" });
193196
+ const resolved = dtf.resolvedOptions();
193197
+ if (resolved.calendar !== "gregory" || resolved.numberingSystem !== "latn")
193198
+ return null;
193199
+ parts = dtf.formatToParts(PROBE_UTC);
193200
+ } catch {
193201
+ return null;
193202
+ }
193203
+ let pattern = "";
193204
+ for (const part of parts) {
193205
+ switch (part.type) {
193206
+ case "year":
193207
+ if (part.value !== "2001")
193208
+ return null;
193209
+ pattern += "YYYY";
193210
+ break;
193211
+ case "month":
193212
+ if (part.value === "2")
193213
+ pattern += "M";
193214
+ else if (part.value === "02")
193215
+ pattern += "MM";
193216
+ else
193217
+ return null;
193218
+ break;
193219
+ case "day":
193220
+ if (part.value === "3")
193221
+ pattern += "D";
193222
+ else if (part.value === "03")
193223
+ pattern += "DD";
193224
+ else
193225
+ return null;
193226
+ break;
193227
+ case "literal":
193228
+ if (/[YMD]/.test(part.value))
193229
+ return null;
193230
+ pattern += part.value;
193231
+ break;
193232
+ default:
193233
+ return null;
193234
+ }
193235
+ }
193236
+ if (!pattern.includes("YYYY") || !/M/.test(pattern) || !/D/.test(pattern))
193237
+ return null;
193238
+ return pattern;
193239
+ }
193240
+ function matchToLocaleDateStringCall(callee, args, metadata) {
193241
+ if (callee.kind !== "member" || callee.computed)
193242
+ return null;
193243
+ if (callee.property !== "toLocaleDateString" || args.length !== 2)
193244
+ return null;
193245
+ const [locale, options] = args;
193246
+ if (locale.kind !== "literal" || locale.literalType !== "string")
193247
+ return null;
193248
+ if (options.kind !== "object-literal" || options.properties.length !== 1)
193249
+ return null;
193250
+ const prop = options.properties[0];
193251
+ if (prop.key !== "timeZone")
193252
+ return null;
193253
+ if (prop.value.kind !== "literal" || prop.value.literalType !== "string")
193254
+ return null;
193255
+ const tz = String(prop.value.value);
193256
+ if (!TO_LOCALE_TZ_RE.test(tz))
193257
+ return null;
193258
+ const receiverType = resolveReceiverType(callee.object, metadata, new Map);
193259
+ if (!receiverType || receiverType.kind !== "interface")
193260
+ return null;
193261
+ const typeName = baseTypeName(receiverType.raw);
193262
+ if (typeName !== "Date")
193263
+ return null;
193264
+ if (metadata.typeDefinitions.some((d) => d.name === typeName))
193265
+ return null;
193266
+ const pattern = resolveLocaleDatePattern(String(locale.value));
193267
+ if (pattern === null)
193268
+ return null;
193269
+ return {
193270
+ kind: "helper-call",
193271
+ helper: "format_date",
193272
+ args: [
193273
+ callee.object,
193274
+ { kind: "literal", value: pattern, literalType: "string" },
193275
+ { kind: "literal", value: tz, literalType: "string" }
193276
+ ]
193277
+ };
193278
+ }
193279
+ var toLocaleDatePlugin = {
193280
+ name: "toLocaleDateString",
193281
+ prepare(metadata) {
193282
+ if (!metadata.propsType || !typeReachesDate(metadata.propsType, metadata, new Set))
193283
+ return null;
193284
+ return (callee, args) => matchToLocaleDateStringCall(callee, args, metadata);
193285
+ }
193286
+ };
193287
+
192795
193288
  // ../jsx/src/jsx-to-ir.ts
192796
193289
  var CLIENT_DIRECTIVE_INTERIOR_RE2 = /^\s*@client\s*$/;
192797
193290
  var BLOCK_COMMENT_RE2 = /\/\*([\s\S]*?)\*\//g;
@@ -192886,6 +193379,19 @@ function getDateLoweringMatcher(ctx) {
192886
193379
  }
192887
193380
  return ctx._dateLoweringMatcher;
192888
193381
  }
193382
+ function getToLocaleDateLoweringMatcher(ctx) {
193383
+ if (ctx._toLocaleDateLoweringMatcher === undefined) {
193384
+ const a = ctx.analyzer;
193385
+ const metadataSlice = {
193386
+ propsType: a.propsType,
193387
+ propsObjectName: a.propsObjectName,
193388
+ propsParams: a.propsParams,
193389
+ typeDefinitions: a.typeDefinitions
193390
+ };
193391
+ ctx._toLocaleDateLoweringMatcher = toLocaleDatePlugin.prepare(metadataSlice);
193392
+ }
193393
+ return ctx._toLocaleDateLoweringMatcher;
193394
+ }
192889
193395
  function lowerDateCalls(text, expr, ctx) {
192890
193396
  const matcher = getDateLoweringMatcher(ctx);
192891
193397
  if (!matcher)
@@ -192914,8 +193420,38 @@ function lowerDateCalls(text, expr, ctx) {
192914
193420
  }
192915
193421
  return restore(result);
192916
193422
  }
193423
+ function lowerToLocaleDateCalls(text, expr, ctx) {
193424
+ const matcher = getToLocaleDateLoweringMatcher(ctx);
193425
+ if (!matcher)
193426
+ return text;
193427
+ const candidates = [];
193428
+ function visit2(n) {
193429
+ if (import_typescript11.default.isCallExpression(n) && n.arguments.length === 2 && import_typescript11.default.isPropertyAccessExpression(n.expression) && !n.expression.questionDotToken && n.expression.name.text === "toLocaleDateString") {
193430
+ candidates.push(n);
193431
+ }
193432
+ import_typescript11.default.forEachChild(n, visit2);
193433
+ }
193434
+ visit2(expr);
193435
+ if (candidates.length === 0)
193436
+ return text;
193437
+ const { protect, restore, replaceProtectedCall } = createTemplateAwareStringProtector();
193438
+ let result = protect(text);
193439
+ for (const call of candidates) {
193440
+ const propAccess = call.expression;
193441
+ const node = matcher(tsNodeToParsedExpr(propAccess), call.arguments.map((a) => tsNodeToParsedExpr(a)));
193442
+ if (!node || node.kind !== "helper-call" || node.helper !== "format_date")
193443
+ continue;
193444
+ const [, patternArg, tzArg] = node.args;
193445
+ if (patternArg?.kind !== "literal" || tzArg?.kind !== "literal")
193446
+ continue;
193447
+ const receiverText = ctx.getJS(propAccess.expression);
193448
+ const matchText = ctx.getJS(call);
193449
+ result = replaceProtectedCall(result, matchText, () => `formatDate(${receiverText}, ${JSON.stringify(patternArg.value)}, ${JSON.stringify(tzArg.value)})`);
193450
+ }
193451
+ return restore(result);
193452
+ }
192917
193453
  function rewriteBarePropRefs2(text, expr, ctx) {
192918
- const dateLowered = lowerDateCalls(text, expr, ctx);
193454
+ const dateLowered = lowerToLocaleDateCalls(lowerDateCalls(text, expr, ctx), expr, ctx);
192919
193455
  let propNames = getDestructuredPropNames(ctx);
192920
193456
  if (!propNames)
192921
193457
  return dateLowered === text ? undefined : dateLowered;
@@ -196332,7 +196868,7 @@ var ENV_SIGNAL_READERS = new Map([
196332
196868
  function queryHrefLocalNames(metadata) {
196333
196869
  const names = new Set;
196334
196870
  for (const imp of metadata.imports) {
196335
- if (!QUERY_HREF_SOURCES.has(imp.source) || imp.isTypeOnly)
196871
+ if (!CLIENT_HELPER_SOURCES.has(imp.source) || imp.isTypeOnly)
196336
196872
  continue;
196337
196873
  for (const s of imp.specifiers) {
196338
196874
  if (s.isTypeOnly || s.isNamespace || s.isDefault)
@@ -196343,10 +196879,24 @@ function queryHrefLocalNames(metadata) {
196343
196879
  }
196344
196880
  return names;
196345
196881
  }
196346
- var QUERY_HREF_SOURCES = new Set([
196882
+ var CLIENT_HELPER_SOURCES = new Set([
196347
196883
  "@barefootjs/client",
196348
196884
  "@barefootjs/client/runtime"
196349
196885
  ]);
196886
+ function formatDateLocalNames(metadata) {
196887
+ const names = new Set;
196888
+ for (const imp of metadata.imports) {
196889
+ if (!CLIENT_HELPER_SOURCES.has(imp.source) || imp.isTypeOnly)
196890
+ continue;
196891
+ for (const s of imp.specifiers) {
196892
+ if (s.isTypeOnly || s.isNamespace || s.isDefault)
196893
+ continue;
196894
+ if (s.name === "formatDate")
196895
+ names.add(s.alias ?? s.name);
196896
+ }
196897
+ }
196898
+ return names;
196899
+ }
196350
196900
 
196351
196901
  // ../jsx/src/ir-to-client-js/emit-reactive.ts
196352
196902
  var import_typescript14 = __toESM(require_typescript(), 1);
@@ -196955,6 +197505,29 @@ function isOmitBranch(node) {
196955
197505
  }
196956
197506
  return false;
196957
197507
  }
197508
+ // ../jsx/src/format-date-lowering.ts
197509
+ var UTC_LITERAL = { kind: "literal", value: "UTC", literalType: "string" };
197510
+ function matchFormatDateCall(callee, args, locals) {
197511
+ if (callee.kind !== "identifier" || !locals.has(callee.name))
197512
+ return null;
197513
+ if (args.length < 2 || args.length > 3)
197514
+ return null;
197515
+ return {
197516
+ kind: "helper-call",
197517
+ helper: "format_date",
197518
+ args: [args[0], args[1], args[2] ?? UTC_LITERAL]
197519
+ };
197520
+ }
197521
+ var formatDatePlugin = {
197522
+ name: "formatDate",
197523
+ prepare(metadata) {
197524
+ const locals = formatDateLocalNames(metadata);
197525
+ if (locals.size === 0)
197526
+ return null;
197527
+ return (callee, args) => matchFormatDateCall(callee, args, locals);
197528
+ }
197529
+ };
197530
+
196958
197531
  // ../jsx/src/builtin-lowering-plugins.ts
196959
197532
  var queryHrefPlugin = {
196960
197533
  name: "queryHref",
@@ -196968,7 +197541,12 @@ var queryHrefPlugin = {
196968
197541
  };
196969
197542
  }
196970
197543
  };
196971
- var BUILTIN_LOWERING_PLUGINS = [queryHrefPlugin, datePlugin];
197544
+ var BUILTIN_LOWERING_PLUGINS = [
197545
+ queryHrefPlugin,
197546
+ datePlugin,
197547
+ formatDatePlugin,
197548
+ toLocaleDatePlugin
197549
+ ];
196972
197550
  function registerBuiltinLoweringPlugins() {
196973
197551
  for (const plugin of BUILTIN_LOWERING_PLUGINS)
196974
197552
  registerLoweringPlugin(plugin);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/test",
3
- "version": "0.21.3",
3
+ "version": "0.23.0",
4
4
  "description": "Test utilities for BarefootJS - IR-based component testing without a browser",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,7 +39,7 @@
39
39
  "directory": "packages/test"
40
40
  },
41
41
  "dependencies": {
42
- "@barefootjs/jsx": "0.21.3"
42
+ "@barefootjs/jsx": "0.23.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.0.0"